aboutsummaryrefslogtreecommitdiff
path: root/src/client/views/nodes/WebBox.tsx
diff options
context:
space:
mode:
authorSophie Zhang <sophie_zhang@brown.edu>2023-03-06 16:33:39 -0500
committerSophie Zhang <sophie_zhang@brown.edu>2023-03-06 16:33:39 -0500
commit3a6f179aedf8e148fe9828426b43aa31ca87bcb1 (patch)
tree9f49ba8d54bda361826c17cfe7f3cb0a37854ace /src/client/views/nodes/WebBox.tsx
parentc6425a0469727305f76d00e3f8c545e04aad61cc (diff)
parent4c2584baf8bae0cde714c832b0768d3c08864422 (diff)
Merge branch 'master' into pres-trail-sophie
Diffstat (limited to 'src/client/views/nodes/WebBox.tsx')
-rw-r--r--src/client/views/nodes/WebBox.tsx124
1 files changed, 68 insertions, 56 deletions
diff --git a/src/client/views/nodes/WebBox.tsx b/src/client/views/nodes/WebBox.tsx
index 43b3b0536..5f9420a54 100644
--- a/src/client/views/nodes/WebBox.tsx
+++ b/src/client/views/nodes/WebBox.tsx
@@ -1,5 +1,5 @@
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
-import { action, computed, IReactionDisposer, observable, ObservableMap, reaction, runInAction, trace } from 'mobx';
+import { action, computed, IReactionDisposer, observable, ObservableMap, reaction, runInAction } from 'mobx';
import { observer } from 'mobx-react';
import * as WebRequest from 'web-request';
import { Doc, DocListCast, HeightSym, Opt, WidthSym } from '../../../fields/Doc';
@@ -11,8 +11,9 @@ import { listSpec } from '../../../fields/Schema';
import { Cast, ImageCast, NumCast, StrCast } from '../../../fields/Types';
import { ImageField, WebField } from '../../../fields/URLField';
import { TraceMobx } from '../../../fields/util';
-import { emptyFunction, getWordAtPoint, OmitKeys, returnEmptyString, returnFalse, returnOne, setupMoveUpEvents, smoothScroll, StopEvent, Utils } from '../../../Utils';
+import { emptyFunction, getWordAtPoint, OmitKeys, returnFalse, returnOne, setupMoveUpEvents, smoothScroll, StopEvent, Utils } from '../../../Utils';
import { Docs, DocUtils } from '../../documents/Documents';
+import { DocumentManager } from '../../util/DocumentManager';
import { ScriptingGlobals } from '../../util/ScriptingGlobals';
import { SnappingManager } from '../../util/SnappingManager';
import { undoBatch, UndoManager } from '../../util/UndoManager';
@@ -21,7 +22,6 @@ import { CollectionFreeFormView } from '../collections/collectionFreeForm/Collec
import { ContextMenu } from '../ContextMenu';
import { ContextMenuProps } from '../ContextMenuItem';
import { ViewBoxAnnotatableComponent, ViewBoxAnnotatableProps } from '../DocComponent';
-import { DocumentDecorations } from '../DocumentDecorations';
import { Colors } from '../global/globalEnums';
import { LightboxView } from '../LightboxView';
import { MarqueeAnnotator } from '../MarqueeAnnotator';
@@ -29,14 +29,14 @@ import { AnchorMenu } from '../pdf/AnchorMenu';
import { Annotation } from '../pdf/Annotation';
import { SidebarAnnos } from '../SidebarAnnos';
import { StyleProp } from '../StyleProvider';
-import { DocFocusOptions, DocumentView, DocumentViewInternal, DocumentViewProps } from './DocumentView';
+import { DocFocusOptions, DocumentView, DocumentViewProps, OpenWhere } from './DocumentView';
import { FieldView, FieldViewProps } from './FieldView';
import { LinkDocPreview } from './LinkDocPreview';
-import { VideoBox } from './VideoBox';
+import { PinProps, PresBox } from './trails';
import './WebBox.scss';
import React = require('react');
import { DragManager } from '../../util/DragManager';
-import { gptSummarize } from '../../apis/gpt/Summarization';
+import { gptAPICall, GPTCallType } from '../../apis/gpt/Summarization';
import { GPTPopup } from '../pdf/GPTPopup';
const { CreateImage } = require('./WebBoxRenderer');
const _global = (window /* browser */ || global) /* node */ as any;
@@ -62,10 +62,9 @@ export class WebBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProps
// GPT Additions
private _summaryText: string = '';
- private _selectionText: string = '';
setSummaryText = async () => {
try {
- const summary = await gptSummarize(this.selectionText());
+ const summary = await gptAPICall(this.selectionText(), GPTCallType.SUMMARY);
this._summaryText = `Summary: ${summary}`;
} catch (err) {
console.log(err);
@@ -73,7 +72,6 @@ export class WebBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProps
}
};
summaryText = () => this._summaryText;
- selectionText = () => this._selectionText;
private get _getAnchor() {
return AnchorMenu.Instance?.GetAnchor;
@@ -107,7 +105,7 @@ export class WebBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProps
return this.allAnnotations.filter(a => a.textInlineAnnotations);
}
@computed get webField() {
- return Cast(this.dataDoc[this.props.fieldKey], WebField)?.url;
+ return Cast(this.rootDoc[this.props.fieldKey], WebField)?.url;
}
@computed get webThumb() {
return (
@@ -180,7 +178,7 @@ export class WebBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProps
console.log('BAD DATA IN THUMB CREATION');
return;
}
- VideoBox.convertDataUri(data_url, this.layoutDoc[Id] + '-icon' + new Date().getTime(), true, this.layoutDoc[Id] + '-icon').then(returnedfilename =>
+ Utils.convertDataUri(data_url, this.layoutDoc[Id] + '-icon' + new Date().getTime(), true, this.layoutDoc[Id] + '-icon').then(returnedfilename =>
setTimeout(
action(() => {
this.rootDoc.thumbLockout = false;
@@ -205,9 +203,10 @@ export class WebBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProps
this._annotationKeySuffix = () => this._urlHash + '-annotations';
const reqdFuncs: { [key: string]: string } = {};
// bcz: need to make sure that doc.data-annotations points to the currently active web page's annotations (this could/should be when the doc is created)
- reqdFuncs[this.fieldKey + '-annotations'] = `copyField(this["${this.fieldKey}-"+urlHash(this["${this.fieldKey}"]?.url?.toString())+"-annotations"`;
- reqdFuncs[this.fieldKey + '-sidebar'] = `copyField(this["${this.fieldKey}-"+urlHash(this["${this.fieldKey}"]?.url?.toString())+"-sidebar"`;
- DocUtils.AssignScripts(this.dataDoc, {}, reqdFuncs);
+ reqdFuncs[this.fieldKey + '-annotations'] = `copyField(this["${this.fieldKey}-"+urlHash(this["${this.fieldKey}"]?.url?.toString())+"-annotations"])`;
+ reqdFuncs[this.fieldKey + '-annotations-setter'] = `this["${this.fieldKey}-"+urlHash(this["${this.fieldKey}"]?.url?.toString())+"-annotations"] = value`;
+ reqdFuncs[this.fieldKey + '-sidebar'] = `copyField(this["${this.fieldKey}-"+urlHash(this["${this.fieldKey}"]?.url?.toString())+"-sidebar"])`;
+ DocUtils.AssignScripts(this.rootDoc, {}, reqdFuncs);
});
reaction(
() => this.props.isSelected(true) || this.isAnyChildContentActive() || Doc.isBrushedHighlightedDegree(this.props.Document),
@@ -274,6 +273,10 @@ export class WebBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProps
// this._iframe?.contentDocument?.removeEventListener("pointerup", this.iframeUp);
}
+ private _selectionText: string = '';
+ private _selectionContent: DocumentFragment | undefined;
+ selectionText = () => this._selectionText;
+ selectionContent = () => this._selectionContent;
@action
createTextAnnotation = (sel: Selection, selRange: Range | undefined) => {
if (this._mainCont.current && selRange) {
@@ -293,6 +296,8 @@ export class WebBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProps
}
}
//this._selectionText = selRange.cloneContents().textContent || "";
+ this._selectionContent = selRange?.cloneContents();
+ this._selectionText = this._selectionContent?.textContent || '';
// clear selection
if (sel.empty) sel.empty(); // Chrome
@@ -304,27 +309,35 @@ export class WebBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProps
setBrushViewer = (func?: (view: { width: number; height: number; panX: number; panY: number }) => void) => (this._setBrushViewer = func);
brushView = (view: { width: number; height: number; panX: number; panY: number }) => this._setBrushViewer?.(view);
- scrollFocus = (doc: Doc, options: DocFocusOptions) => {
- if (this._url && StrCast(doc.webUrl) !== this._url) this.submitURL(StrCast(doc.webUrl), options.instant);
- if (DocListCast(this.props.Document[this.fieldKey + '-sidebar']).includes(doc) && !this.SidebarShown) {
- this.toggleSidebar(options.instant);
- }
- if (this._sidebarRef?.current?.makeDocUnfiltered(doc)) return 1;
- if (doc !== this.rootDoc && this._outerRef.current) {
+ focus = (anchor: Doc, options: DocFocusOptions) => {
+ if (anchor !== this.rootDoc && this._outerRef.current) {
const windowHeight = this.props.PanelHeight() / (this.props.NativeDimScaling?.() || 1);
- const scrollTo = Utils.scrollIntoView(NumCast(doc.y), doc[HeightSym](), NumCast(this.layoutDoc._scrollTop), windowHeight, windowHeight * 0.1, Math.max(NumCast(doc.y) + doc[HeightSym](), this.getScrollHeight()));
- if (scrollTo !== undefined && this._initialScroll === undefined) {
- const focusSpeed = options.instant ? 0 : options.zoomTime ?? 500;
- this.goTo(scrollTo, focusSpeed, options.easeFunc);
- return focusSpeed;
- } else if (!this._webPageHasBeenRendered || !this.getScrollHeight() || this._initialScroll !== undefined) {
- this._initialScroll = scrollTo;
+ const scrollTo = Utils.scrollIntoView(NumCast(anchor.y), anchor[HeightSym](), NumCast(this.layoutDoc._scrollTop), windowHeight, windowHeight * 0.1, Math.max(NumCast(anchor.y) + anchor[HeightSym](), this._scrollHeight));
+ if (scrollTo !== undefined) {
+ if (this._initialScroll === undefined) {
+ this.goTo(scrollTo, options.zoomTime ?? 500, options.easeFunc);
+ } else {
+ this._initialScroll = scrollTo;
+ }
}
}
- return undefined;
};
- getAnchor = (addAsAnnotation: boolean) => {
+ getView = async (doc: Doc) => {
+ if (this.rootDoc.layoutKey === 'layout_icon') this.props.DocumentView?.().iconify();
+ if (this._url && StrCast(doc.webUrl) !== this._url) this.submitURL(StrCast(doc.webUrl));
+ if (this._sidebarRef?.current?.makeDocUnfiltered(doc) && !this.SidebarShown) this.toggleSidebar(false);
+ return new Promise<Opt<DocumentView>>(res => DocumentManager.Instance.AddViewRenderedCb(doc, dv => res(dv)));
+ };
+
+ sidebarAddDocTab = (doc: Doc, where: OpenWhere) => {
+ if (DocListCast(this.props.Document[this.props.fieldKey + '-sidebar']).includes(doc) && !this.SidebarShown) {
+ this.toggleSidebar(false);
+ return true;
+ }
+ return this.props.addDocTab(doc, where);
+ };
+ getAnchor = (addAsAnnotation: boolean, pinProps?: PinProps) => {
let ele: Opt<HTMLDivElement> = undefined;
try {
const contents = this._iframe?.contentWindow?.getSelection()?.getRangeAt(0).cloneContents();
@@ -339,10 +352,13 @@ export class WebBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProps
title: StrCast(this.rootDoc.title + ' ' + this.layoutDoc._scrollTop),
y: NumCast(this.layoutDoc._scrollTop),
unrendered: true,
+ annotationOn: this.rootDoc,
});
+ PresBox.pinDocView(anchor, { pinDocLayout: pinProps?.pinDocLayout, pinData: { ...(pinProps?.pinData ?? {}), scrollable: true, pannable: true } }, this.rootDoc);
anchor.text = ele?.textContent ?? '';
anchor.textHtml = ele?.innerHTML;
- addAsAnnotation && this.addDocumentWrapper(anchor);
+ //addAsAnnotation &&
+ this.addDocumentWrapper(anchor);
return anchor;
};
@@ -398,9 +414,6 @@ export class WebBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProps
ContextMenu.Instance.setIgnoreEvents(true);
}
};
-
- getScrollHeight = () => this._scrollHeight;
-
isFirefox = () => {
return 'InstallTrigger' in window; // navigator.userAgent.indexOf("Chrome") !== -1;
};
@@ -545,14 +558,14 @@ export class WebBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProps
};
forward = (checkAvailable?: boolean) => {
- const future = Cast(this.dataDoc[this.fieldKey + '-future'], listSpec('string'), []);
- const history = Cast(this.dataDoc[this.fieldKey + '-history'], listSpec('string'), []);
+ const future = Cast(this.rootDoc[this.fieldKey + '-future'], listSpec('string'), []);
+ const history = Cast(this.rootDoc[this.fieldKey + '-history'], listSpec('string'), []);
if (checkAvailable) return future.length;
runInAction(() => {
if (future.length) {
const curUrl = this._url;
- this.dataDoc[this.fieldKey + '-history'] = new List<string>([...history, this._url]);
- this.dataDoc[this.fieldKey] = new WebField(new URL(future.pop()!));
+ this.rootDoc[this.fieldKey + '-history'] = new List<string>([...history, this._url]);
+ this.rootDoc[this.fieldKey] = new WebField(new URL(future.pop()!));
if (this._webUrl === this._url) {
this._webUrl = curUrl;
setTimeout(action(() => (this._webUrl = this._url)));
@@ -566,15 +579,15 @@ export class WebBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProps
};
back = (checkAvailable?: boolean) => {
- const future = Cast(this.dataDoc[this.fieldKey + '-future'], listSpec('string'));
- const history = Cast(this.dataDoc[this.fieldKey + '-history'], listSpec('string'), []);
+ const future = Cast(this.rootDoc[this.fieldKey + '-future'], listSpec('string'));
+ const history = Cast(this.rootDoc[this.fieldKey + '-history'], listSpec('string'), []);
if (checkAvailable) return history.length;
runInAction(() => {
if (history.length) {
const curUrl = this._url;
- if (future === undefined) this.dataDoc[this.fieldKey + '-future'] = new List<string>([this._url]);
- else this.dataDoc[this.fieldKey + '-future'] = new List<string>([...future, this._url]);
- this.dataDoc[this.fieldKey] = new WebField(new URL(history.pop()!));
+ if (future === undefined) this.rootDoc[this.fieldKey + '-future'] = new List<string>([this._url]);
+ else this.rootDoc[this.fieldKey + '-future'] = new List<string>([...future, this._url]);
+ this.layoutDoc[this.fieldKey] = new WebField(new URL(history.pop()!));
if (this._webUrl === this._url) {
this._webUrl = curUrl;
setTimeout(action(() => (this._webUrl = this._url)));
@@ -601,11 +614,11 @@ export class WebBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProps
if (!newUrl) return;
if (!newUrl.startsWith('http')) newUrl = 'http://' + newUrl;
try {
- const future = Cast(this.dataDoc[this.fieldKey + '-future'], listSpec('string'));
- const history = Cast(this.dataDoc[this.fieldKey + '-history'], listSpec('string'));
+ const future = Cast(this.rootDoc[this.fieldKey + '-future'], listSpec('string'));
+ const history = Cast(this.rootDoc[this.fieldKey + '-history'], listSpec('string'));
const url = this.webField?.toString();
if (url && !preview) {
- this.dataDoc[this.fieldKey + '-history'] = new List<string>([...(history || []), url]);
+ this.rootDoc[this.fieldKey + '-history'] = new List<string>([...(history || []), url]);
this.layoutDoc._scrollTop = 0;
if (this._webPageHasBeenRendered) {
this.layoutDoc.thumb = undefined;
@@ -616,7 +629,7 @@ export class WebBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProps
future && (future.length = 0);
}
if (!preview) {
- this.dataDoc[this.fieldKey] = new WebField(new URL(newUrl));
+ this.layoutDoc[this.fieldKey] = new WebField(new URL(newUrl));
!dontUpdateIframe && (this._webUrl = this._url);
}
} catch (e) {
@@ -742,7 +755,7 @@ export class WebBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProps
@computed get urlContent() {
if (this._hackHide || (this.webThumb && !this._webPageHasBeenRendered && LightboxView.LightboxDoc !== this.rootDoc)) return null;
this.props.thumbShown?.();
- const field = this.dataDoc[this.props.fieldKey];
+ const field = this.rootDoc[this.props.fieldKey];
let view;
if (field instanceof HtmlField) {
view = <span className="webBox-htmlSpan" contentEditable onPointerDown={e => e.stopPropagation()} dangerouslySetInnerHTML={{ __html: field.html }} />;
@@ -850,7 +863,7 @@ export class WebBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProps
toggleSidebar = action((preview: boolean = false) => {
var nativeWidth = NumCast(this.layoutDoc[this.fieldKey + '-nativeWidth']);
if (!nativeWidth) {
- const defaultNativeWidth = this.dataDoc[this.fieldKey] instanceof WebField ? 850 : this.Document[WidthSym]();
+ const defaultNativeWidth = this.rootDoc[this.fieldKey] instanceof WebField ? 850 : this.Document[WidthSym]();
Doc.SetNativeWidth(this.dataDoc, Doc.NativeWidth(this.dataDoc) || defaultNativeWidth);
Doc.SetNativeHeight(this.dataDoc, Doc.NativeHeight(this.dataDoc) || (this.Document[HeightSym]() / this.Document[WidthSym]()) * defaultNativeWidth);
nativeWidth = NumCast(this.layoutDoc[this.fieldKey + '-nativeWidth']);
@@ -879,8 +892,7 @@ export class WebBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProps
return WebBox.sidebarResizerWidth + nativeDiff * (this.props.NativeDimScaling?.() || 1);
};
@computed get content() {
- const interactive =
- !this.props.docViewPath().lastElement()?.docView?._pendingDoubleClick && this.props.isContentActive() && this.props.pointerEvents?.() !== 'none' && Doc.ActiveTool === InkTool.None && !DocumentDecorations.Instance?.Interacting;
+ const interactive = !this.props.docViewPath().lastElement()?.docView?._pendingDoubleClick && this.props.isContentActive() && this.props.pointerEvents?.() !== 'none' && Doc.ActiveTool === InkTool.None;
return (
<div className={'webBox-cont' + (interactive ? '-interactive' : '')} onKeyDown={e => e.stopPropagation()} style={{ width: !this.layoutDoc.forceReflow ? NumCast(this.layoutDoc[this.fieldKey + '-nativeWidth']) || `100%` : '100%' }}>
{this.urlContent}
@@ -921,6 +933,7 @@ export class WebBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProps
PanelHeight={this.panelHeight}
ScreenToLocalTransform={this.scrollXf}
NativeDimScaling={returnOne}
+ focus={this.focus}
dropAction={'alias'}
docFilters={docFilters}
select={emptyFunction}
@@ -992,8 +1005,8 @@ export class WebBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProps
searchStringChanged = (e: React.ChangeEvent<HTMLInputElement>) => (this._searchString = e.currentTarget.value);
showInfo = action((anno: Opt<Doc>) => (this._overlayAnnoInfo = anno));
setPreviewCursor = (func?: (x: number, y: number, drag: boolean, hide: boolean) => void) => (this._setPreviewCursor = func);
- panelWidth = () => this.props.PanelWidth() / (this.props.NativeDimScaling?.() || 1) - this.sidebarWidth() + WebBox.sidebarResizerWidth; // (this.Document.scrollHeight || Doc.NativeHeight(this.Document) || 0);
- panelHeight = () => this.props.PanelHeight() / (this.props.NativeDimScaling?.() || 1); // () => this._pageSizes.length && this._pageSizes[0] ? this._pageSizes[0].width : Doc.NativeWidth(this.Document);
+ panelWidth = () => this.props.PanelWidth() / (this.props.NativeDimScaling?.() || 1) - this.sidebarWidth() + WebBox.sidebarResizerWidth;
+ panelHeight = () => this.props.PanelHeight() / (this.props.NativeDimScaling?.() || 1);
scrollXf = () => this.props.ScreenToLocalTransform().translate(0, NumCast(this.layoutDoc._scrollTop));
anchorMenuClick = () => this._sidebarRef.current?.anchorMenuClick;
transparentFilter = () => [...this.props.docFilters(), Utils.IsTransparentFilter()];
@@ -1007,6 +1020,7 @@ export class WebBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProps
pointerEvents = () => (!this._draggingSidebar && this.props.isContentActive() && this.props.pointerEvents?.() !== 'none' && !MarqueeOptionsMenu.Instance?.isShown() ? 'all' : SnappingManager.GetIsDragging() ? undefined : 'none');
annotationPointerEvents = () => (this._isAnnotating || SnappingManager.GetIsDragging() || Doc.ActiveTool !== InkTool.None ? 'all' : 'none');
render() {
+ setTimeout(() => DocListCast(this.rootDoc[this.annotationKey]).forEach(doc => (doc.webUrl = this._url)));
const previewScale = this._previewNativeWidth ? 1 - this.sidebarWidth() / this._previewNativeWidth : 1;
const pointerEvents = this.layoutDoc._lockedPosition ? 'none' : (this.props.pointerEvents?.() as any);
const scale = previewScale * (this.props.NativeDimScaling?.() || 1);
@@ -1039,9 +1053,7 @@ export class WebBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProps
docView={this.props.docViewPath().lastElement()}
finishMarquee={this.finishMarquee}
savedAnnotations={this.savedAnnotationsCreator}
- selectionText={returnEmptyString}
- summaryText={this.summaryText}
- setSummaryText={this.setSummaryText}
+ selectionText={this.selectionText}
annotationLayer={this._annotationLayer.current}
mainCont={this._mainCont.current}
/>