aboutsummaryrefslogtreecommitdiff
path: root/src/client/views/pdf
diff options
context:
space:
mode:
authorNathan-SR <144961007+Nathan-SR@users.noreply.github.com>2025-05-30 03:30:12 -0400
committerNathan-SR <144961007+Nathan-SR@users.noreply.github.com>2025-05-30 03:30:12 -0400
commit29e5bbe68e02fe1d86e960a634d0580c37612254 (patch)
treee88585946a58feb988e3a3bb45dd2a9a09fea4c3 /src/client/views/pdf
parentf92a02ec5d676359cb268a35d30e5bf9886199c1 (diff)
parent49fb76f1c54fb8fc4e76bdcf675719d41bfc36aa (diff)
Merge branch 'master' into Template-Changes
Diffstat (limited to 'src/client/views/pdf')
-rw-r--r--src/client/views/pdf/Annotation.tsx7
-rw-r--r--src/client/views/pdf/GPTPopup/GPTPopup.scss11
-rw-r--r--src/client/views/pdf/GPTPopup/GPTPopup.tsx183
-rw-r--r--src/client/views/pdf/PDFViewer.scss7
-rw-r--r--src/client/views/pdf/PDFViewer.tsx65
5 files changed, 149 insertions, 124 deletions
diff --git a/src/client/views/pdf/Annotation.tsx b/src/client/views/pdf/Annotation.tsx
index 1891cfd4c..e8a5235c9 100644
--- a/src/client/views/pdf/Annotation.tsx
+++ b/src/client/views/pdf/Annotation.tsx
@@ -50,7 +50,7 @@ interface IAnnotationProps extends FieldViewProps {
}
@observer
export class Annotation extends ObservableReactComponent<IAnnotationProps> {
- constructor(props: any) {
+ constructor(props: IAnnotationProps) {
super(props);
makeObservable(this);
}
@@ -58,7 +58,7 @@ export class Annotation extends ObservableReactComponent<IAnnotationProps> {
@computed get linkHighlighted() {
const found = LinkManager.Instance.getAllDirectLinks(this._props.annoDoc).find(link => {
const a1 = Doc.getOppositeAnchor(link, this._props.annoDoc);
- return a1 && Doc.GetBrushStatus(DocCast(a1.annotationOn, a1));
+ return a1 && Doc.GetBrushStatus(DocCast(a1.annotationOn, a1)!);
});
return found;
}
@@ -112,6 +112,7 @@ export class Annotation extends ObservableReactComponent<IAnnotationProps> {
outline = () => (this.linkHighlighted ? 'solid 1px lightBlue' : undefined);
background = () => (this._props.annoDoc[Highlight] ? 'orange' : StrCast(this._props.annoDoc.backgroundColor));
render() {
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
const forceRenderHack = [this.background(), this.outline(), this.opacity()]; // forces a re-render when these change -- because RegionAnnotation doesn't do this internally..
return (
<div style={{ display: this._props.annoDoc.textCopied && !Doc.GetBrushHighlightStatus(this._props.annoDoc) ? 'none' : undefined }}>
@@ -121,7 +122,7 @@ export class Annotation extends ObservableReactComponent<IAnnotationProps> {
.map(([x, y, width, height]) => (
<div
key={'' + x + y + width + height}
- style={{ pointerEvents: this._props.pointerEvents?.() as any }}
+ style={{ pointerEvents: this._props.pointerEvents?.() as Property.PointerEvents }}
onPointerDown={this.onPointerDown}
onContextMenu={this.onContextMenu}
onPointerEnter={() => {
diff --git a/src/client/views/pdf/GPTPopup/GPTPopup.scss b/src/client/views/pdf/GPTPopup/GPTPopup.scss
index 18441f76e..f6fa45221 100644
--- a/src/client/views/pdf/GPTPopup/GPTPopup.scss
+++ b/src/client/views/pdf/GPTPopup/GPTPopup.scss
@@ -7,8 +7,15 @@ $highlightedText: #82e0ff;
$inputHeight: 60px;
$headingHeight: 32px;
+.gptPopup-sortBox {
+ display: block;
+ max-height: calc(100% - 45px); // leave room for input
+}
+
.gptPopup-summary-box {
position: fixed;
+ padding-left: 10px;
+ padding-right: 10px;
top: 115px;
left: 75px;
width: 100%;
@@ -48,7 +55,6 @@ $headingHeight: 32px;
}
label {
- color: $textgrey;
font-size: 12px;
font-weight: 400;
letter-spacing: 1px;
@@ -73,7 +79,6 @@ $headingHeight: 32px;
justify-content: center;
align-items: center;
height: $inputHeight;
- background-color: white;
width: 100%;
pointer-events: all;
@@ -87,6 +92,7 @@ $headingHeight: 32px;
}
.btns-wrapper-gpt {
height: 100%;
+ width: 100%;
display: flex;
justify-content: center;
align-items: center;
@@ -97,7 +103,6 @@ $headingHeight: 32px;
flex-direction: column;
width: 100%;
height: 100%;
- overflow-y: auto;
padding-right: 5px;
}
diff --git a/src/client/views/pdf/GPTPopup/GPTPopup.tsx b/src/client/views/pdf/GPTPopup/GPTPopup.tsx
index 67213382d..568e48edf 100644
--- a/src/client/views/pdf/GPTPopup/GPTPopup.tsx
+++ b/src/client/views/pdf/GPTPopup/GPTPopup.tsx
@@ -93,7 +93,7 @@ export class GPTPopup extends ObservableReactComponent<object> {
this.onGptResponse = (sortResult: string, questionType: GPTDocCommand, args?: string) => this.processGptResponse(selDoc, this._textToDocMap, sortResult, questionType, args);
this.onQuizRandom = () => this.randomlyChooseDoc(selDoc.Document, hasChildDocs());
this._documentDescriptions = Promise.all(hasChildDocs().map(doc =>
- Doc.getDescription(doc).then(text => this._textToDocMap.set(text.trim(), doc) && `${DescriptionSeperator}${text}${DescriptionSeperator}`)
+ Doc.getDescription(doc).then(text => this._textToDocMap.set(text.replace(/\n/g, ' ').trim(), doc) && `${DescriptionSeperator}${text}${DescriptionSeperator}`)
)).then(docDescriptions => docDescriptions.join()); // prettier-ignore
}
},
@@ -210,8 +210,8 @@ export class GPTPopup extends ObservableReactComponent<object> {
generateFireflyImage = (imgDesc: string) => {
const selView = DocumentView.Selected().lastElement();
const selDoc = selView?.Document;
- if (selDoc && (selView._props.renderDepth > 1 || selDoc[Doc.LayoutFieldKey(selDoc)] instanceof ImageField)) {
- const oldPrompt = StrCast(selDoc.ai_firefly_prompt, StrCast(selDoc.title));
+ if (selDoc && (selView._props.renderDepth > 1 || selDoc[Doc.LayoutDataKey(selDoc)] instanceof ImageField)) {
+ const oldPrompt = StrCast(selDoc.ai_prompt, StrCast(selDoc.title));
const newPrompt = oldPrompt ? `${oldPrompt} ~~~ ${imgDesc}` : imgDesc;
return DrawingFillHandler.drawingToImage(selDoc, 100, newPrompt, selDoc)
.then(action(() => (this._userPrompt = '')))
@@ -406,70 +406,80 @@ export class GPTPopup extends ObservableReactComponent<object> {
scrollToBottom = () => setTimeout(() => this._messagesEndRef.current?.scrollIntoView({ behavior: 'smooth', block: 'end' }), 50);
gptMenu = () => (
- <div className="btns-wrapper-gpt">
- <Button
- tooltip="Ask Firefly to create images"
- text="Ask Firefly"
- onClick={() => this.setMode(GPTPopupMode.FIREFLY)}
- color={StrCast(Doc.UserDoc().userVariantColor)}
- type={Type.TERT}
- style={{
- width: '100%',
- height: '40%',
- textAlign: 'center',
- color: '#ffffff',
- fontSize: '16px',
- marginBottom: '10px',
- }}
- />
- <Button
- tooltip="Ask GPT to sort, tag, define, or filter your Docs!"
- text="Ask GPT"
- onClick={() => this.setMode(GPTPopupMode.USER_PROMPT)}
- color={StrCast(Doc.UserDoc().userVariantColor)}
- type={Type.TERT}
- style={{
- width: '100%',
- height: '40%',
- textAlign: 'center',
- color: '#ffffff',
- fontSize: '16px',
- marginBottom: '10px',
- }}
- />
- <Button
- tooltip="Test your knowledge by verifying answers with ChatGPT"
- text="Take Quiz"
- onClick={() => {
- this._conversationArray = ['Define the selected card!'];
- this.setMode(GPTPopupMode.QUIZ_RESPONSE);
- this.onQuizRandom?.();
- }}
- color={StrCast(Doc.UserDoc().userVariantColor)}
- type={Type.TERT}
- style={{
- width: '100%',
- height: '40%',
- textAlign: 'center',
- color: '#ffffff',
- fontSize: '16px',
- }}
- />
+ <div style={{ display: 'flex', maxHeight: 'calc(100% - 32px)', overflow: 'auto' }}>
+ <div className="btns-wrapper-gpt">
+ <Button
+ tooltip="Ask Firefly to create images"
+ text="Ask Firefly"
+ onClick={() => this.setMode(GPTPopupMode.FIREFLY)}
+ color={SettingsManager.userColor}
+ background={SettingsManager.userVariantColor}
+ type={Type.TERT}
+ style={{
+ width: '100%',
+ height: '40%',
+ textAlign: 'center',
+ color: '#ffffff',
+ fontSize: '16px',
+ marginBottom: '10px',
+ }}
+ />
+ <Button
+ tooltip="Ask GPT to sort, tag, define, or filter your Docs!"
+ text="Ask GPT"
+ onClick={() => this.setMode(GPTPopupMode.USER_PROMPT)}
+ color={SettingsManager.userColor}
+ background={SettingsManager.userVariantColor}
+ type={Type.TERT}
+ style={{
+ width: '100%',
+ height: '40%',
+ textAlign: 'center',
+ color: '#ffffff',
+ fontSize: '16px',
+ marginBottom: '10px',
+ }}
+ />
+ <Button
+ tooltip="Test your knowledge by verifying answers with ChatGPT"
+ text="Take Quiz"
+ onClick={() => {
+ this._conversationArray = ['Define the selected card!'];
+ this.setMode(GPTPopupMode.QUIZ_RESPONSE);
+ this.onQuizRandom?.();
+ }}
+ color={SettingsManager.userColor}
+ background={SettingsManager.userVariantColor}
+ type={Type.TERT}
+ style={{
+ width: '100%',
+ height: '40%',
+ textAlign: 'center',
+ color: '#ffffff',
+ fontSize: '16px',
+ }}
+ />
+ </div>
</div>
);
callGpt = action((mode: GPTPopupMode) => {
this.setGptProcessing(true);
+ const reset = action(() => {
+ this.setGptProcessing(false);
+ this._userPrompt = '';
+ this._quizAnswer = '';
+ });
switch (mode) {
case GPTPopupMode.FIREFLY:
this._fireflyArray.push(this._userPrompt);
- return this.generateFireflyImage(this._userPrompt).then(action(() => (this._userPrompt = '')));
+ return this.generateFireflyImage(this._userPrompt).then(reset);
case GPTPopupMode.USER_PROMPT:
this._conversationArray.push(this._userPrompt);
- return this.generateUserPromptResponse(this._userPrompt).then(action(() => (this._userPrompt = '')));
+ return this.generateUserPromptResponse(this._userPrompt).then(reset);
case GPTPopupMode.QUIZ_RESPONSE:
this._conversationArray.push(this._quizAnswer);
- return this.generateQuizAnswerAnalysis(DocumentView.SelectedDocs().lastElement(), this._quizAnswer).then(action(() => (this._quizAnswer = '')));
+ return this.generateQuizAnswerAnalysis(DocumentView.SelectedDocs().lastElement(), this._quizAnswer).then(reset);
}
});
@@ -487,18 +497,20 @@ export class GPTPopup extends ObservableReactComponent<object> {
};
gptUserInput = () => (
- <div className="btns-wrapper-gpt">
- <div className="chat-wrapper">
- <div className="chat-bubbles">
- {(this._mode === GPTPopupMode.FIREFLY ? this._fireflyArray : this._conversationArray).map((message, index) => (
- <div key={index} className={`chat-bubble ${index % 2 === 1 ? 'user-message' : 'chat-message'}`}>
- {message}
- </div>
- ))}
- {this._gptProcessing && <div className="chat-bubble chat-message">...</div>}
- </div>
+ <div style={{ display: 'flex', maxHeight: 'calc(100% - 32px)', overflow: 'auto' }}>
+ <div className="btns-wrapper-gpt">
+ <div className="chat-wrapper">
+ <div className="chat-bubbles">
+ {(this._mode === GPTPopupMode.FIREFLY ? this._fireflyArray : this._conversationArray).map((message, index) => (
+ <div key={index} className={`chat-bubble ${index % 2 === 1 ? 'user-message' : 'chat-message'}`}>
+ {message}
+ </div>
+ ))}
+ {this._gptProcessing && <div className="chat-bubble chat-message">...</div>}
+ </div>
- <div ref={this._messagesEndRef} style={{ height: '100px' }} />
+ <div ref={this._messagesEndRef} style={{ height: '40px' }} />
+ </div>
</div>
</div>
);
@@ -517,6 +529,7 @@ export class GPTPopup extends ObservableReactComponent<object> {
onChange={e => onChange(e.target.value)}
onKeyDown={e => this.handleKeyPress(e, this._mode)}
type="text"
+ style={{ color: 'black' }}
placeholder={placeholder}
/>
<Button //
@@ -524,7 +537,8 @@ export class GPTPopup extends ObservableReactComponent<object> {
type={Type.TERT}
icon={<AiOutlineSend />}
iconPlacement="right"
- color={SnappingManager.userVariantColor}
+ color={SettingsManager.userColor}
+ background={SettingsManager.userVariantColor}
onClick={() => this.callGpt(this._mode)}
/>
<DictationButton ref={r => (this._askDictation = r)} setInput={onChange} />
@@ -551,7 +565,7 @@ export class GPTPopup extends ObservableReactComponent<object> {
</div>
</div>
<div key={rawSrc[0] + i + 'btn'} className="btn-container">
- <Button text="Save Image" onClick={() => this.transferToImage(rawSrc[1])} color={StrCast(Doc.UserDoc().userColor)} type={Type.TERT} />
+ <Button text="Save Image" onClick={() => this.transferToImage(rawSrc[1])} color={SettingsManager.userColor} background={SettingsManager.userVariantColor} type={Type.TERT} />
</div>
</>
))}
@@ -561,7 +575,8 @@ export class GPTPopup extends ObservableReactComponent<object> {
tooltip="Generate Again"
onClick={() => this._imgTargetDoc && this.generateImage(this._imageDescription, this._imgTargetDoc, this._addToCollection)}
icon={<FontAwesomeIcon icon="redo-alt" size="lg" />}
- color={StrCast(Doc.UserDoc().userVariantColor)}
+ color={SettingsManager.userColor}
+ background={SettingsManager.userVariantColor}
/>
)}
</div>
@@ -603,14 +618,16 @@ export class GPTPopup extends ObservableReactComponent<object> {
tooltip="Show originally selected text" //
text="Selection"
onClick={action(() => (this._showOriginal = true))}
- color={StrCast(SettingsManager.userVariantColor)}
+ color={SettingsManager.userColor}
+ background={SettingsManager.userVariantColor}
type={Type.TERT}
/>
<Button
tooltip="Create a text Doc with this text and link to the text selection" //
text="Transfer To Text"
onClick={this.transferToText}
- color={StrCast(SettingsManager.userVariantColor)}
+ color={SettingsManager.userColor}
+ background={SettingsManager.userVariantColor}
type={Type.TERT}
/>
</>
@@ -627,14 +644,16 @@ export class GPTPopup extends ObservableReactComponent<object> {
}
this.generateSummary(this._aiReferenceText);
})}
- color={StrCast(SettingsManager.userVariantColor)}
+ color={SettingsManager.userColor}
+ background={SettingsManager.userVariantColor}
type={Type.TERT}
/>
<Button
tooltip="Create Flashcards" //
text="Create Flashcards"
onClick={this.createFlashcards}
- color={StrCast(SettingsManager.userVariantColor)}
+ color={SettingsManager.userColor}
+ background={SettingsManager.userVariantColor}
type={Type.TERT}
/>
</>
@@ -644,7 +663,7 @@ export class GPTPopup extends ObservableReactComponent<object> {
<div className="summarizing">
<span>{this._showOriginal ? 'Creating Cards...' : 'Summarizing'}</span>
<ReactLoading type="bubbles" color="#bcbcbc" width={20} height={20} />
- <Button text="Stop Animation" onClick={() => this.setStopAnimatingResponse(true)} color={StrCast(SettingsManager.userVariantColor)} type={Type.TERT} />
+ <Button text="Stop Animation" onClick={() => this.setStopAnimatingResponse(true)} color={SettingsManager.userColor} background={SettingsManager.userVariantColor} type={Type.TERT} />
</div>
)}
</div>
@@ -689,19 +708,19 @@ export class GPTPopup extends ObservableReactComponent<object> {
placeholder="Ask GPT a question about the data..."
id="search-input"
className="searchBox-input"
- style={{ width: '100%' }}
+ style={{ width: '100%', color: SnappingManager.userColor }}
/>
) : (
<>
- <Button tooltip="Transfer to text" text="Transfer To Text" onClick={this.transferToText} color={StrCast(SnappingManager.userVariantColor)} type={Type.TERT} />
- <Button tooltip="Chat with AI" text="Chat with AI" onClick={() => this.setChatEnabled(true)} color={StrCast(SnappingManager.userVariantColor)} type={Type.TERT} />
+ <Button tooltip="Transfer to text" text="Transfer To Text" onClick={this.transferToText} color={SettingsManager.userColor} background={SettingsManager.userVariantColor} type={Type.TERT} />
+ <Button tooltip="Chat with AI" text="Chat with AI" onClick={() => this.setChatEnabled(true)} color={SettingsManager.userColor} background={SettingsManager.userVariantColor} type={Type.TERT} />
</>
)
) : (
<div className="summarizing">
<span>Summarizing</span>
<ReactLoading type="bubbles" color="#bcbcbc" width={20} height={20} />
- <Button text="Stop Animation" onClick={() => this.setStopAnimatingResponse(true)} color={StrCast(SnappingManager.userVariantColor)} type={Type.TERT} />
+ <Button text="Stop Animation" onClick={() => this.setStopAnimatingResponse(true)} color={SettingsManager.userColor} background={SettingsManager.userVariantColor} type={Type.TERT} />
</div>
)}
</div>
@@ -718,7 +737,7 @@ export class GPTPopup extends ObservableReactComponent<object> {
);
heading = (headingText: string) => (
- <div className="summary-heading">
+ <div className="summary-heading" style={{ color: SnappingManager.userBackgroundColor }}>
<label className="summary-text">{headingText}</label>
{this._gptProcessing ? (
<ReactLoading type="spin" color="#bcbcbc" width={14} height={14} />
@@ -734,7 +753,7 @@ export class GPTPopup extends ObservableReactComponent<object> {
onClick={() => this._collectionContext && Doc.setDocFilter(this._collectionContext, 'tags', GPTPopup.ChatTag, 'remove')}
/>
{[GPTPopupMode.USER_PROMPT, GPTPopupMode.QUIZ_RESPONSE, GPTPopupMode.FIREFLY].includes(this._mode) && (
- <IconButton color={StrCast(SettingsManager.userVariantColor)} tooltip="back" icon={<CgCornerUpLeft size="16px" />} onClick={() => (this._mode = GPTPopupMode.GPT_MENU)} />
+ <IconButton color={SettingsManager.userVariantColor} background={SettingsManager.userColor} tooltip="back" icon={<CgCornerUpLeft size="16px" />} onClick={action(() => (this._mode = GPTPopupMode.GPT_MENU))} />
)}
</>
)}
@@ -743,12 +762,12 @@ export class GPTPopup extends ObservableReactComponent<object> {
render() {
return (
- <div className="gptPopup-summary-box" style={{ display: SnappingManager.ChatVisible ? 'flex' : 'none', overflow: 'auto' }}>
+ <div className="gptPopup-summary-box" style={{ background: SnappingManager.userColor, color: SnappingManager.userBackgroundColor, display: SnappingManager.ChatVisible ? 'flex' : 'none' }}>
{(() => {
//prettier-ignore
switch (this._mode) {
case GPTPopupMode.USER_PROMPT: return this.promptBox("ASK", this._userPrompt, this.setUserPrompt, 'Ask GPT to sort, tag, define, or filter your documents for you!');
- case GPTPopupMode.FIREFLY: return this.promptBox("CREATE", this._userPrompt, this.setUserPrompt, StrCast(DocumentView.Selected().lastElement()?.Document.ai_firefly_prompt, 'Ask Firefly to generate images'));
+ case GPTPopupMode.FIREFLY: return this.promptBox("CREATE", this._userPrompt, this.setUserPrompt, StrCast(DocumentView.Selected().lastElement()?.Document.ai_prompt, 'Ask Firefly to generate images'));
case GPTPopupMode.QUIZ_RESPONSE: return this.promptBox("QUIZ", this._quizAnswer, this.setQuizAnswer, 'Describe/answer the selected document!');
case GPTPopupMode.GPT_MENU: return this.menuBox();
case GPTPopupMode.SUMMARY: return this.summaryBox();
diff --git a/src/client/views/pdf/PDFViewer.scss b/src/client/views/pdf/PDFViewer.scss
index 030251762..a54505443 100644
--- a/src/client/views/pdf/PDFViewer.scss
+++ b/src/client/views/pdf/PDFViewer.scss
@@ -29,7 +29,11 @@
.textLayer {
opacity: unset;
mix-blend-mode: multiply; // bcz: makes text fuzzy!
+ // all these below fix issues with PDFjs
transform: scale(var(--devicePixelRatio));
+ --total-scale-factor: var(--scale-factor); // these 3 are used by PDFjs but not defined. why???
+ --scale-round-x: 1px;
+ --scale-round-y: 1px;
}
[data-main-rotation='90'] {
transform: scale(var(--devicePixelRatio)) rotate(90deg) translateY(-100%);
@@ -114,6 +118,9 @@
.pdfViewerDash-interactive {
pointer-events: all;
+ &::-webkit-scrollbar {
+ width: 40px;
+ }
}
.loading-spinner {
diff --git a/src/client/views/pdf/PDFViewer.tsx b/src/client/views/pdf/PDFViewer.tsx
index 83b3dffe5..97fe183dd 100644
--- a/src/client/views/pdf/PDFViewer.tsx
+++ b/src/client/views/pdf/PDFViewer.tsx
@@ -1,9 +1,10 @@
import { action, computed, IReactionDisposer, makeObservable, observable, ObservableMap, reaction, runInAction } from 'mobx';
import { observer } from 'mobx-react';
import * as Pdfjs from 'pdfjs-dist';
+import { GlobalWorkerOptions } from 'pdfjs-dist/build/pdf.mjs';
import * as PDFJSViewer from 'pdfjs-dist/web/pdf_viewer.mjs';
-import 'pdfjs-dist/webpack.mjs'; // sets the PDF workerSrc
import * as React from 'react';
+import ReactLoading from 'react-loading';
import { addStyleSheet, addStyleSheetRule, clearStyleSheetRules, ClientUtils, returnAll, returnFalse, returnNone, returnZero, smoothScroll } from '../../../ClientUtils';
import { CreateLinkToActiveAudio, Doc, DocListCast, Opt } from '../../../fields/Doc';
import { DocData, Height } from '../../../fields/DocSymbols';
@@ -14,6 +15,7 @@ import { TraceMobx } from '../../../fields/util';
import { emptyFunction, numberRange, unimplementedFunction } from '../../../Utils';
import { DocUtils } from '../../documents/DocUtils';
import { SnappingManager } from '../../util/SnappingManager';
+import { Transform } from '../../util/Transform';
import { MarqueeOptionsMenu } from '../collections/collectionFreeForm';
import { CollectionFreeFormView } from '../collections/collectionFreeForm/CollectionFreeFormView';
import { MarqueeAnnotator } from '../MarqueeAnnotator';
@@ -28,12 +30,13 @@ import { AnchorMenu } from './AnchorMenu';
import { Annotation } from './Annotation';
import { GPTPopup } from './GPTPopup/GPTPopup';
import './PDFViewer.scss';
-import ReactLoading from 'react-loading';
-import { Transform } from '../../util/Transform';
+import { DocumentViewProps } from '../nodes/DocumentContentsView';
+if (window?.Worker) GlobalWorkerOptions.workerSrc = 'files/node_modules/pdfjs-dist/build/pdf.worker.min.mjs'; // npm start/etc use copyfiles to copy the worker from the pdfjs-dist package to the public folder
+export * from 'pdfjs-dist/build/pdf.mjs';
interface IViewerProps extends FieldViewProps {
pdfBox: PDFBox;
- Document: Doc;
+ Doc: Doc;
dataDoc: Doc;
layoutDoc: Doc;
fieldKey: string;
@@ -52,7 +55,7 @@ interface IViewerProps extends FieldViewProps {
*/
@observer
export class PDFViewer extends ObservableReactComponent<IViewerProps> {
- static _annotationStyle = addStyleSheet();
+ static _annotationStyle = addStyleSheet().sheet;
constructor(props: IViewerProps) {
super(props);
@@ -111,8 +114,8 @@ export class PDFViewer extends ObservableReactComponent<IViewerProps> {
() => this._props.layoutDoc._layout_autoHeight,
layoutAutoHeight => {
if (layoutAutoHeight) {
- this._props.layoutDoc._nativeHeight = NumCast(this._props.Document[this._props.fieldKey + '_nativeHeight']);
- this._props.setHeight?.(NumCast(this._props.Document[this._props.fieldKey + '_nativeHeight']) * (this._props.NativeDimScaling?.() || 1));
+ this._props.layoutDoc._nativeHeight = NumCast(this._props.Doc[this._props.fieldKey + '_nativeHeight']);
+ this._props.setHeight?.(NumCast(this._props.Doc[this._props.fieldKey + '_nativeHeight']) * (this._props.NativeDimScaling?.() || 1));
}
}
);
@@ -123,7 +126,7 @@ export class PDFViewer extends ObservableReactComponent<IViewerProps> {
{ fireImmediately: true }
);
this._disposers.curPage = reaction(
- () => Cast(this._props.Document._layout_curPage, 'number', null),
+ () => Cast(this._props.Doc._layout_curPage, 'number', null),
page => page !== undefined && page !== this._pdfViewer?.currentPageNumber && this.gotoPage(page),
{ fireImmediately: true }
);
@@ -131,7 +134,7 @@ export class PDFViewer extends ObservableReactComponent<IViewerProps> {
componentWillUnmount = () => {
Object.values(this._disposers).forEach(disposer => disposer?.());
- document.removeEventListener('copy', this.copy);
+ document.removeEventListener('copy', this.copy, true);
};
copy = (e: ClipboardEvent) => {
@@ -143,6 +146,7 @@ export class PDFViewer extends ObservableReactComponent<IViewerProps> {
e.clipboardData.setData('dash/pdfAnchor', anchor[DocData][Id]);
}
e.preventDefault();
+ e.stopPropagation();
}
};
@@ -179,7 +183,7 @@ export class PDFViewer extends ObservableReactComponent<IViewerProps> {
scrollFocus = (doc: Doc, scrollTop: number, options: FocusViewOptions) => {
const mainCont = this._mainCont.current;
let focusSpeed: Opt<number>;
- if (doc !== this._props.Document && mainCont) {
+ if (doc !== this._props.Doc && mainCont) {
const windowHeight = this._props.PanelHeight() / (this._props.NativeDimScaling?.() || 1);
const scrollTo = ClientUtils.scrollIntoView(scrollTop, doc[Height](), NumCast(this._props.layoutDoc._layout_scrollTop), windowHeight, windowHeight * 0.1, this._scrollHeight);
if (scrollTo !== undefined && scrollTo !== this._props.layoutDoc._layout_scrollTop) {
@@ -214,11 +218,11 @@ export class PDFViewer extends ObservableReactComponent<IViewerProps> {
{ fireImmediately: true }
);
this._disposers.scroll = reaction(
- () => Math.abs(NumCast(this._props.Document._layout_scrollTop)),
+ () => Math.abs(NumCast(this._props.Doc._layout_scrollTop)),
pos => {
if (!this._ignoreScroll) {
this._showWaiting && this.setupPdfJsViewer();
- const viewTrans = quickScroll?.loc ?? StrCast(this._props.Document._viewTransition);
+ const viewTrans = quickScroll?.loc ?? StrCast(this._props.Doc._viewTransition);
const durationMiliStr = viewTrans.match(/([0-9]*)ms/);
const durationSecStr = viewTrans.match(/([0-9.]*)s/);
const duration = durationMiliStr ? Number(durationMiliStr[1]) : durationSecStr ? Number(durationSecStr[1]) * 1000 : 0;
@@ -259,16 +263,11 @@ export class PDFViewer extends ObservableReactComponent<IViewerProps> {
}
return;
}
- document.removeEventListener('copy', this.copy);
- document.addEventListener('copy', this.copy);
+ document.removeEventListener('copy', this.copy, true);
+ document.addEventListener('copy', this.copy, true);
const eventBus = new PDFJSViewer.EventBus();
eventBus._on('pagesinit', this.pagesinit);
- eventBus._on(
- 'pagerendered',
- action(() => {
- this._showWaiting = false;
- })
- );
+ eventBus._on('pagerendered',action(() => (this._showWaiting = false))); // prettier-ignore
const pdfLinkService = new PDFJSViewer.PDFLinkService({ eventBus });
const pdfFindController = new PDFJSViewer.PDFFindController({ linkService: pdfLinkService, eventBus });
this._pdfViewer = new PDFJSViewer.PDFViewer({
@@ -360,18 +359,12 @@ export class PDFViewer extends ObservableReactComponent<IViewerProps> {
@action
onPointerDown = (e: React.PointerEvent): void => {
- // const hit = document.elementFromPoint(e.clientX, e.clientY);
- // bcz: Change. drag selecting requires that preventDefault is NOT called. This used to happen in DocumentView,
- // but that's changed, so this shouldn't be needed.
- // if (hit && hit.localName === "span" && this.annotationsActive(true)) { // drag selecting text stops propagation
- // e.button === 0 && e.stopPropagation();
- // }
// if alt+left click, drag and annotate
this._downX = e.clientX;
this._downY = e.clientY;
- if ((this._props.Document._freeform_scale || 1) !== 1) return;
+ if ((this._props.Doc._freeform_scale || 1) !== 1) return;
if ((e.button !== 0 || e.altKey) && this._props.isContentActive()) {
- this._setPreviewCursor?.(e.clientX, e.clientY, true, false, this._props.Document);
+ this._setPreviewCursor?.(e.clientX, e.clientY, true, false, this._props.Doc);
}
if (!e.altKey && e.button === 0 && this._props.isContentActive() && Doc.ActiveTool !== InkTool.Ink) {
this._props.select(false);
@@ -429,9 +422,9 @@ export class PDFViewer extends ObservableReactComponent<IViewerProps> {
};
addDrawingAnnotation = (drawing: Doc) => {
- // drawing[DocData].x = this._props.pdfBox.ScreenToLocalBoxXf().TranslateX
+ // drawing.x = this._props.pdfBox.ScreenToLocalBoxXf().TranslateX
// const scaleX = this._mainCont.current.offsetWidth / boundingRect.width;
- drawing.y = NumCast(drawing.y) + NumCast(this._props.Document.layout_scrollTop);
+ drawing.y = NumCast(drawing.y) + NumCast(this._props.Doc.layout_scrollTop);
this._props.addDocument?.(drawing);
};
@@ -476,7 +469,7 @@ export class PDFViewer extends ObservableReactComponent<IViewerProps> {
onClick = (e: React.MouseEvent) => {
this._scrollStopper?.();
if (this._setPreviewCursor && e.button === 0 && Math.abs(e.clientX - this._downX) < ClientUtils.DRAG_THRESHOLD && Math.abs(e.clientY - this._downY) < ClientUtils.DRAG_THRESHOLD) {
- this._setPreviewCursor(e.clientX, e.clientY, false, false, this._props.Document);
+ this._setPreviewCursor(e.clientX, e.clientY, false, false, this._props.Doc);
}
// e.stopPropagation(); // bcz: not sure why this was here. We need to allow the DocumentView to get clicks to process doubleClicks
};
@@ -504,7 +497,7 @@ export class PDFViewer extends ObservableReactComponent<IViewerProps> {
@computed get annotationLayer() {
const inlineAnnos = this.inlineTextAnnotations.sort((a, b) => NumCast(a.y) - NumCast(b.y)).filter(anno => !anno.hidden);
return (
- <div className="pdfViewerDash-annotationLayer" style={{ height: Doc.NativeHeight(this._props.Document), transform: `scale(${NumCast(this._props.layoutDoc._freeform_scale, 1)})` }} ref={this._annotationLayer}>
+ <div className="pdfViewerDash-annotationLayer" style={{ height: Doc.NativeHeight(this._props.Doc), transform: `scale(${NumCast(this._props.layoutDoc._freeform_scale, 1)})` }} ref={this._annotationLayer}>
{inlineAnnos.map(anno => (
<Annotation {...this._props} fieldKey={this._props.fieldKey + '_annotations'} pointerEvents={this.pointerEvents} containerDataDoc={this._props.dataDoc} annoDoc={anno} key={`${anno[Id]}-annotation`} />
))}
@@ -519,7 +512,7 @@ export class PDFViewer extends ObservableReactComponent<IViewerProps> {
panelHeight = () => this._props.PanelHeight() / (this._props.NativeDimScaling?.() || 1);
transparentFilter = () => [...this._props.childFilters(), ClientUtils.TransparentBackgroundFilter];
opaqueFilter = () => [...this._props.childFilters(), ClientUtils.noDragDocsFilter, ...(SnappingManager.CanEmbed && this._props.isContentActive() ? [] : [ClientUtils.OpaqueBackgroundFilter])];
- childStyleProvider = (doc: Doc | undefined, props: Opt<FieldViewProps>, property: string) => {
+ childStyleProvider = (doc: Doc | undefined, props: Opt<FieldViewProps & DocumentViewProps>, property: string) => {
if (doc instanceof Doc && property === StyleProp.PointerEvents) {
if (this.inlineTextAnnotations.includes(doc) || this._props.isContentActive() === false) return 'none';
const isInk = doc.layout_isSvg && !props?.LayoutTemplateString;
@@ -595,7 +588,7 @@ export class PDFViewer extends ObservableReactComponent<IViewerProps> {
onClick={this.onClick}
style={{
overflowX: NumCast(this._props.layoutDoc._freeform_scale, 1) !== 1 ? 'scroll' : undefined,
- height: !this._props.Document._layout_fitWidth && window.screen.width > 600 ? Doc.NativeHeight(this._props.Document) : `100%`,
+ height: !this._props.Doc._layout_fitWidth && window.screen.width > 600 ? Doc.NativeHeight(this._props.Doc) : `100%`,
}}>
{this.pdfViewerDiv}
{this.annotationLayer}
@@ -604,12 +597,12 @@ export class PDFViewer extends ObservableReactComponent<IViewerProps> {
{!this._mainCont.current || !this._annotationLayer.current || !this.props.pdfBox.DocumentView ? null : (
<MarqueeAnnotator
ref={this._marqueeref}
- Document={this._props.Document}
+ Document={this._props.Doc}
getPageFromScroll={this.getPageFromScroll}
anchorMenuClick={this._props.anchorMenuClick}
scrollTop={0}
annotationLayerScaling={() => Pdfjs.PixelsPerInch.PDF_TO_CSS_UNITS}
- annotationLayerScrollTop={NumCast(this._props.Document._layout_scrollTop)}
+ annotationLayerScrollTop={NumCast(this._props.Doc._layout_scrollTop)}
addDocument={this.addDocumentWrapper}
docView={this.props.pdfBox.DocumentView}
screenTransform={this.screenToMarqueeXf}