aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorbobzel <zzzman@gmail.com>2021-03-11 13:59:54 -0500
committerbobzel <zzzman@gmail.com>2021-03-11 13:59:54 -0500
commit61deb85209901707dda51413f975ba09e835a1e9 (patch)
treee268bdb7f69994149813bda305dbb6be509a7334
parent1c562c545580f473f9f8a5113914290cd2590b0c (diff)
added optional stacking sidebar for PDFs. fixed pdfannos to not show linkbutton when selected. fixed stacking views to handle fitwidth text better (make height fit correctly when fitWidth)
-rw-r--r--src/client/documents/Documents.ts2
-rw-r--r--src/client/util/CurrentUserUtils.ts2
-rw-r--r--src/client/views/StyleProvider.tsx2
-rw-r--r--src/client/views/collections/CollectionMasonryViewFieldRow.tsx4
-rw-r--r--src/client/views/collections/CollectionStackingView.tsx19
-rw-r--r--src/client/views/collections/CollectionSubView.tsx5
-rw-r--r--src/client/views/nodes/DocumentLinksButton.tsx6
-rw-r--r--src/client/views/nodes/PDFBox.tsx37
-rw-r--r--src/client/views/pdf/PDFViewer.tsx11
9 files changed, 65 insertions, 23 deletions
diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts
index d1102f01b..8912a6c41 100644
--- a/src/client/documents/Documents.ts
+++ b/src/client/documents/Documents.ts
@@ -815,7 +815,7 @@ export namespace Docs {
export function PdfDocument(url: string, options: DocumentOptions = {}) {
const pdfProto = Prototypes.get(DocumentType.PDF);
pdfProto._fitWidth = true; // backward compatibility -- can be removed after db is reset
- return InstanceFromProto(pdfProto, new PdfField(new URL(url)), options);
+ return InstanceFromProto(pdfProto, new PdfField(new URL(url)), { _viewType: "stacking", ...options });
}
export function WebDocument(url: string, options: DocumentOptions = {}) {
diff --git a/src/client/util/CurrentUserUtils.ts b/src/client/util/CurrentUserUtils.ts
index cb8676c5f..ba1a32785 100644
--- a/src/client/util/CurrentUserUtils.ts
+++ b/src/client/util/CurrentUserUtils.ts
@@ -1194,7 +1194,7 @@ export class CurrentUserUtils {
public static GetNewTextDoc(title: string, x: number, y: number, width?: number, height?: number, noMargins?: boolean, annotationOn?: Doc, maxHeight?: number) {
const tbox = Docs.Create.TextDocument("", {
_xMargin: noMargins ? 0 : undefined, _yMargin: noMargins ? 0 : undefined, annotationOn, docMaxAutoHeight: maxHeight,
- _width: width || 200, _height: height || 100, x: x, y: y, _autoHeight: true, _fontSize: StrCast(Doc.UserDoc().fontSize),
+ _width: width || 200, _height: height || 100, x: x, y: y, _fitWidth: true, _autoHeight: true, _fontSize: StrCast(Doc.UserDoc().fontSize),
_fontFamily: StrCast(Doc.UserDoc().fontFamily), title
});
const template = FormattedTextBox.DefaultLayout;
diff --git a/src/client/views/StyleProvider.tsx b/src/client/views/StyleProvider.tsx
index 2352aa22a..e1337abf3 100644
--- a/src/client/views/StyleProvider.tsx
+++ b/src/client/views/StyleProvider.tsx
@@ -74,7 +74,7 @@ export function DefaultStyleProvider(doc: Opt<Doc>, props: Opt<FieldViewProps |
case StyleProp.DocContents: return undefined;
case StyleProp.WidgetColor: return isAnnotated ? "lightBlue" : darkScheme() ? "lightgrey" : "dimgrey";
case StyleProp.Opacity: return Cast(doc?._opacity, "number", Cast(doc?.opacity, "number", null));
- case StyleProp.HideLinkButton: return isAnchor || props?.dontRegisterView || (!selected && (doc?.isLinkButton || doc?.hideLinkButton));
+ case StyleProp.HideLinkButton: return isAnchor || props?.dontRegisterView || ((!selected || doc?.type == DocumentType.PDFANNO) && (doc?.isLinkButton || doc?.hideLinkButton));
case StyleProp.ShowTitle: return doc && !doc.presentationTargetDoc && StrCast(doc._showTitle,
!Doc.IsSystem(doc) && doc.type === DocumentType.RTF ?
(doc.author === Doc.CurrentUserEmail ? StrCast(Doc.UserDoc().showTitle) : "author;creationDate") : "") || "";
diff --git a/src/client/views/collections/CollectionMasonryViewFieldRow.tsx b/src/client/views/collections/CollectionMasonryViewFieldRow.tsx
index 654727a82..9b57d4c68 100644
--- a/src/client/views/collections/CollectionMasonryViewFieldRow.tsx
+++ b/src/client/views/collections/CollectionMasonryViewFieldRow.tsx
@@ -144,13 +144,13 @@ export class CollectionMasonryViewFieldRow extends React.Component<CMVFieldRowPr
if (!value && !forceEmptyNote) return false;
this._createAliasSelected = false;
const key = StrCast(this.props.parent.props.Document._pivotField);
- const newDoc = Docs.Create.TextDocument("", { _autoHeight: true, _width: 200, title: value });
+ const newDoc = Docs.Create.TextDocument("", { _autoHeight: true, _width: 200, _fitWidth: true, title: value });
const onLayoutDoc = this.onLayoutDoc(key);
FormattedTextBox.SelectOnLoad = newDoc[Id];
FormattedTextBox.SelectOnLoadChar = value;
(onLayoutDoc ? newDoc : newDoc[DataSym])[key] = this.getValue(this.props.heading);
const docs = this.props.parent.childDocList;
- return docs ? (docs.splice(0, 0, newDoc) ? true : false) : this.props.parent.props.addDocument?.(newDoc) || false;
+ return docs ? (docs.splice(0, 0, newDoc) ? true : false) : this.props.parent.props.addDocument?.(newDoc) || false; // should really extend addDocument to specify insertion point (at beginning of list)
}
deleteRow = undoBatch(action(() => {
diff --git a/src/client/views/collections/CollectionStackingView.tsx b/src/client/views/collections/CollectionStackingView.tsx
index b4a8974f0..80653ec94 100644
--- a/src/client/views/collections/CollectionStackingView.tsx
+++ b/src/client/views/collections/CollectionStackingView.tsx
@@ -54,7 +54,7 @@ export class CollectionStackingView extends CollectionSubView<StackingDocument,
@computed get chromeStatus() { return this.props.chromeStatus || StrCast(this.layoutDoc._chromeStatus); }
@computed get columnHeaders() { return Cast(this.layoutDoc._columnHeaders, listSpec(SchemaHeaderField)); }
@computed get pivotField() { return StrCast(this.layoutDoc._pivotField); }
- @computed get filteredChildren() { return this.childLayoutPairs.filter(pair => pair.layout instanceof Doc && !pair.layout.hidden).map(pair => pair.layout); }
+ @computed get filteredChildren() { return this.childLayoutPairs.filter(pair => pair.layout instanceof Doc).map(pair => pair.layout); }
@computed get headerMargin() { return this.props.styleProvider?.(this.layoutDoc, this.props, StyleProp.HeaderMargin); }
@computed get xMargin() { return NumCast(this.layoutDoc._xMargin, 2 * Math.min(this.gridGap, .05 * this.props.PanelWidth())); }
@computed get yMargin() { return this.props.yMargin || NumCast(this.layoutDoc._yMargin, 5); } // 2 * this.gridGap)); }
@@ -265,7 +265,7 @@ export class CollectionStackingView extends CollectionSubView<StackingDocument,
return maxWidth / (this.props.scaling?.() || 1);
}
getDocHeight(d?: Doc) {
- if (!d) return 0;
+ if (!d || d.hidden) return 0;
const childLayoutDoc = Doc.Layout(d, this.props.childLayoutTemplate?.());
const childDataDoc = (!d.isTemplateDoc && !d.isTemplateForField && !d.PARAMS) ? undefined : this.props.DataDoc;
const maxHeight = (lim => lim === 0 ? this.props.PanelWidth() : lim === -1 ? 10000 : lim)(NumCast(this.layoutDoc.childLimitHeight, -1));
@@ -280,7 +280,7 @@ export class CollectionStackingView extends CollectionSubView<StackingDocument,
}
const childHeight = NumCast(childLayoutDoc._height);
const panelHeight = this.props.PanelHeight() - 2 * this.yMargin;
- return Math.min(childHeight, maxHeight, panelHeight) / (this.props.scaling?.() || 1);;
+ return Math.min(childHeight, maxHeight, panelHeight);// / (this.props.scaling?.() || 1);;
}
columnDividerDown = (e: React.PointerEvent) => {
@@ -331,10 +331,21 @@ export class CollectionStackingView extends CollectionSubView<StackingDocument,
}
}
}
+ if (de.complete.annoDragData?.dragDocument && super.onInternalDrop(e, de)) return this.internalAnchorAnnoDrop(e, de.complete.annoDragData);
return false;
}
@undoBatch
+ internalAnchorAnnoDrop(e: Event, annoDragData: DragManager.AnchorAnnoDragData) {
+ const dropCreator = annoDragData.dropDocCreator;
+ annoDragData.dropDocCreator = (annotationOn: Doc | undefined) => {
+ const dropDoc = dropCreator(annotationOn);
+ return dropDoc || this.rootDoc;
+ };
+ return true;
+ }
+
+ @undoBatch
@action
onExternalDrop = async (e: React.DragEvent): Promise<void> => {
const where = [e.clientX, e.clientY];
@@ -486,6 +497,7 @@ export class CollectionStackingView extends CollectionSubView<StackingDocument,
@computed get scaling() { return !this.nativeWidth ? 1 : this.props.PanelHeight() / this.nativeHeight; }
+ @computed get backgroundEvents() { return SnappingManager.GetIsDragging(); }
observer: any;
render() {
TraceMobx();
@@ -504,6 +516,7 @@ export class CollectionStackingView extends CollectionSubView<StackingDocument,
height: `${1 / this.scaling * 100}%`,
width: `${1 / this.scaling * 100}%`,
transformOrigin: "top left",
+ pointerEvents: this.backgroundEvents ? "all" : undefined
}}
onScroll={action(e => this._scroll = e.currentTarget.scrollTop)}
onDrop={this.onExternalDrop.bind(this)}
diff --git a/src/client/views/collections/CollectionSubView.tsx b/src/client/views/collections/CollectionSubView.tsx
index 59e1824c1..c63779f44 100644
--- a/src/client/views/collections/CollectionSubView.tsx
+++ b/src/client/views/collections/CollectionSubView.tsx
@@ -66,9 +66,7 @@ export function CollectionSubView<T, X>(schemaCtor: (doc: Doc) => T, moreProps?:
@computed get dataField() {
// sets the dataDoc's data field to an empty list if the data field is undefined - prevents issues with addonly
// setTimeout changes it outside of the @computed section
- setTimeout(() => {
- if (!this.dataDoc[this.props.fieldKey]) this.dataDoc[this.props.fieldKey] = new List<Doc>();
- }, 1000);
+ !this.dataDoc[this.props.fieldKey] && setTimeout(() => this.dataDoc[this.props.fieldKey] = new List<Doc>());
return this.dataDoc[this.props.fieldKey];
}
@@ -480,7 +478,6 @@ import { FormattedTextBox, GoogleRef } from "../nodes/formattedText/FormattedTex
import { CollectionView, CollectionViewType, CollectionViewProps } from "./CollectionView";
import { SelectionManager } from "../../util/SelectionManager";
import { OverlayView } from "../OverlayView";
-import { setTimeout } from "timers";
import { Hypothesis } from "../../util/HypothesisUtils";
import { GetEffectiveAcl } from "../../../fields/util";
diff --git a/src/client/views/nodes/DocumentLinksButton.tsx b/src/client/views/nodes/DocumentLinksButton.tsx
index d62061aea..6f102213b 100644
--- a/src/client/views/nodes/DocumentLinksButton.tsx
+++ b/src/client/views/nodes/DocumentLinksButton.tsx
@@ -276,7 +276,7 @@ export class DocumentLinksButton extends React.Component<DocumentLinksButtonProp
</div >;
}
- @computed get linkButton() {
+ render() {
TraceMobx();
const menuTitle = this.props.StartLink ? "Drag or tap to start link" : "Tap to complete link";
@@ -295,8 +295,4 @@ export class DocumentLinksButton extends React.Component<DocumentLinksButtonProp
</Tooltip>
: this.linkButtonInner;
}
-
- render() {
- return this.linkButton;
- }
}
diff --git a/src/client/views/nodes/PDFBox.tsx b/src/client/views/nodes/PDFBox.tsx
index c0e0296fe..9732fdfb6 100644
--- a/src/client/views/nodes/PDFBox.tsx
+++ b/src/client/views/nodes/PDFBox.tsx
@@ -9,7 +9,7 @@ import { makeInterface } from "../../../fields/Schema";
import { Cast, NumCast, StrCast } from '../../../fields/Types';
import { PdfField } from "../../../fields/URLField";
import { TraceMobx } from '../../../fields/util';
-import { Utils, returnOne } from '../../../Utils';
+import { Utils, returnOne, OmitKeys, emptyFunction } from '../../../Utils';
import { KeyCodes } from '../../util/KeyCodes';
import { undoBatch } from '../../util/UndoManager';
import { panZoomSchema } from '../collections/collectionFreeForm/CollectionFreeFormView';
@@ -24,6 +24,8 @@ import "./PDFBox.scss";
import React = require("react");
import { DocAfterFocusFunc } from './DocumentView';
import { Docs } from '../../documents/Documents';
+import { CollectionStackingView } from '../collections/CollectionStackingView';
+import { StyleProp } from '../StyleProvider';
type PdfDocument = makeInterface<[typeof documentSchema, typeof panZoomSchema, typeof pageSchema]>;
const PdfDocument = makeInterface(documentSchema, panZoomSchema, pageSchema);
@@ -107,6 +109,7 @@ export class PDFBox extends ViewBoxAnnotatableComponent<FieldViewProps, PdfDocum
}, { fireImmediately: true });
}
+ @action
loaded = (nw: number, nh: number, np: number) => {
this.dataDoc[this.props.fieldKey + "-numPages"] = np;
Doc.SetNativeWidth(this.dataDoc, Math.max(Doc.NativeWidth(this.dataDoc), nw * 96 / 72));
@@ -114,6 +117,36 @@ export class PDFBox extends ViewBoxAnnotatableComponent<FieldViewProps, PdfDocum
this.layoutDoc._height = this.layoutDoc[WidthSym]() / (Doc.NativeAspect(this.dataDoc) || 1);
!this.Document._fitWidth && (this.Document._height = this.Document[WidthSym]() * (nh / nw));
}
+ sidebarKey = () => this.fieldKey + "-sidebar";
+ sidebarTransform = () => this.props.ScreenToLocalTransform().translate(Doc.NativeWidth(this.dataDoc), 0);
+ sidebarWidth = () => (NumCast(this.layoutDoc.nativeWidth) - Doc.NativeWidth(this.dataDoc)) * this.props.PanelWidth() / NumCast(this.layoutDoc.nativeWidth);
+ sidebarAddDocument = (doc: Doc | Doc[]) => this.addDocument(doc, this.sidebarKey());
+ sidebarMoveDocument = (doc: Doc | Doc[], targetCollection: Doc, addDocument: (doc: Doc | Doc[]) => boolean) => this.moveDocument(doc, targetCollection, addDocument, this.sidebarKey());
+ sidebarRemDocument = (doc: Doc | Doc[]) => this.removeDocument(doc, this.sidebarKey());
+ @computed get sidebarOverlay() {
+ return !this.layoutDoc._showSidebar ? (null) :
+ <div style={{ position: "absolute", pointerEvents: this.active() ? "all" : undefined, background: this.props.styleProvider?.(this.rootDoc, this.props, StyleProp.BackgroundColor), top: 0, right: 0, width: this.sidebarWidth(), height: "100%" }}>
+ <CollectionStackingView {...OmitKeys(this.props, ["NativeWidth", "NativeHeight", "setContentView"]).omit}
+ isAnnotationOverlay={true}
+ fieldKey={this.sidebarKey()}
+ PanelHeight={this.props.PanelHeight}
+ PanelWidth={this.sidebarWidth}
+ dropAction={"alias"}
+ pointerEvents={"all"}
+ select={emptyFunction}
+ active={this.annotationsActive}
+ ContentScaling={returnOne}
+ bringToFront={emptyFunction}
+ whenActiveChanged={this.whenActiveChanged}
+ childPointerEvents={true}
+ removeDocument={this.sidebarRemDocument}
+ moveDocument={this.sidebarMoveDocument}
+ addDocument={this.sidebarAddDocument}
+ CollectionView={undefined}
+ ScreenToLocalTransform={this.sidebarTransform}
+ renderDepth={this.props.renderDepth + 1} />
+ </div>;
+ }
public search = (string: string, fwd: boolean) => { this._pdfViewer?.search(string, fwd); };
public prevAnnotation = () => { this._pdfViewer?.prevAnnotation(); };
@@ -204,6 +237,7 @@ export class PDFBox extends ViewBoxAnnotatableComponent<FieldViewProps, PdfDocum
const funcs: ContextMenuProps[] = [];
pdfUrl && funcs.push({ description: "Copy path", event: () => Utils.CopyText(pdfUrl.url.pathname), icon: "expand-arrows-alt" });
funcs.push({ description: "Toggle Fit Width " + (this.Document._fitWidth ? "Off" : "On"), event: () => this.Document._fitWidth = !this.Document._fitWidth, icon: "expand-arrows-alt" });
+ !Doc.UserDoc().noviceMode && funcs.push({ description: "Toggle Sidebar mode ", event: () => this.Document._showSidebar = !this.Document._showSidebar, icon: "expand-arrows-alt" });
ContextMenu.Instance.addItem({ description: "Options...", subitems: funcs, icon: "asterisk" });
}
@@ -235,6 +269,7 @@ export class PDFBox extends ViewBoxAnnotatableComponent<FieldViewProps, PdfDocum
startupLive={true}
ContentScaling={this.props.scaling}
/>
+ {this.sidebarOverlay}
{this.settingsPanel()}
</div>;
}
diff --git a/src/client/views/pdf/PDFViewer.tsx b/src/client/views/pdf/PDFViewer.tsx
index 73aea9737..c134ac8d4 100644
--- a/src/client/views/pdf/PDFViewer.tsx
+++ b/src/client/views/pdf/PDFViewer.tsx
@@ -16,7 +16,6 @@ import { DocUtils } from "../../documents/Documents";
import { Networking } from "../../Network";
import { CompiledScript, CompileScript } from "../../util/Scripting";
import { SelectionManager } from "../../util/SelectionManager";
-import { SharingManager } from "../../util/SharingManager";
import { SnappingManager } from "../../util/SnappingManager";
import { CollectionFreeFormView } from "../collections/collectionFreeForm/CollectionFreeFormView";
import { ViewBoxAnnotatableComponent } from "../DocComponent";
@@ -28,6 +27,7 @@ import { Annotation } from "./Annotation";
import "./PDFViewer.scss";
const pdfjs = require('pdfjs-dist/es5/build/pdf.js');
import React = require("react");
+import { SharingManager } from "../../util/SharingManager";
const PDFJSViewer = require("pdfjs-dist/web/pdf_viewer");
const pdfjsLib = require("pdfjs-dist");
const _global = (window /* browser */ || global /* node */) as any;
@@ -173,8 +173,10 @@ export class PDFViewer extends ViewBoxAnnotatableComponent<IViewerProps, PdfDocu
width: (page.view[page0or180 ? 2 : 3] - page.view[page0or180 ? 0 : 1]),
height: (page.view[page0or180 ? 3 : 2] - page.view[page0or180 ? 1 : 0])
});
- i === this.props.pdf.numPages - 1 && this.props.loaded?.((page.view[page0or180 ? 2 : 3] - page.view[page0or180 ? 0 : 1]),
- (page.view[page0or180 ? 3 : 2] - page.view[page0or180 ? 1 : 0]), i);
+ if (i === this.props.pdf.numPages - 1) {
+ this.props.loaded?.(page.view[page0or180 ? 2 : 3] - page.view[page0or180 ? 0 : 1],
+ page.view[page0or180 ? 3 : 2] - page.view[page0or180 ? 1 : 0], i);
+ }
}))));
this.Document.scrollHeight = this._pageSizes.reduce((size, page) => size + page.height, 0) * 96 / 72;
}
@@ -532,8 +534,7 @@ export class PDFViewer extends ViewBoxAnnotatableComponent<IViewerProps, PdfDocu
addDocument={this.addDocument}
CollectionView={undefined}
ScreenToLocalTransform={this.overlayTransform}
- renderDepth={this.props.renderDepth + 1}>
- </CollectionFreeFormView>
+ renderDepth={this.props.renderDepth + 1} />
</div>;
}
@computed get pdfViewerDiv() {