diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/Utils.ts | 4 | ||||
-rw-r--r-- | src/client/util/DocumentManager.ts | 51 | ||||
-rw-r--r-- | src/client/views/collections/TabDocView.tsx | 2 | ||||
-rw-r--r-- | src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx | 56 | ||||
-rw-r--r-- | src/client/views/nodes/DocumentView.tsx | 5 | ||||
-rw-r--r-- | src/client/views/nodes/WebBox.tsx | 4 |
6 files changed, 67 insertions, 55 deletions
diff --git a/src/Utils.ts b/src/Utils.ts index 061c74611..770cef283 100644 --- a/src/Utils.ts +++ b/src/Utils.ts @@ -192,8 +192,8 @@ export namespace Utils { } export function scrollIntoView(targetY: number, targetHgt: number, scrollTop: number, contextHgt: number) { - if (scrollTop + contextHgt < targetY + Math.max(targetHgt * 1.1, 100)) { - return Math.min(scrollTop, targetY + Math.max(targetHgt * 1.1, 100) - contextHgt); + if (scrollTop + contextHgt < targetY + targetHgt * 1.1) { + return targetY + targetHgt * 1.1 - contextHgt; } else if (scrollTop > targetY - targetHgt * .1) { return Math.max(0, targetY - targetHgt * .1); } diff --git a/src/client/util/DocumentManager.ts b/src/client/util/DocumentManager.ts index ac7710d34..e5ef924d6 100644 --- a/src/client/util/DocumentManager.ts +++ b/src/client/util/DocumentManager.ts @@ -143,45 +143,52 @@ export class DocumentManager { finished?: () => void, ): Promise<void> => { const getFirstDocView = LightboxView.LightboxDoc ? DocumentManager.Instance.getLightboxDocumentView : DocumentManager.Instance.getFirstDocumentView; - const focusAndFinish = () => { finished?.(); return false; }; + const docView = getFirstDocView(targetDoc, originatingDoc); + const focusAndFinish = (didFocus: boolean) => { + if (originatingDoc?.isPushpin) { + if (!didFocus || targetDoc.hidden) { + targetDoc.hidden = !targetDoc.hidden; + } + } else { + targetDoc.hidden && (targetDoc.hidden = undefined); + docView?.select(false); + } + finished?.(); + return false; + }; const highlight = () => { const finalDocView = getFirstDocView(targetDoc); finalDocView && Doc.linkFollowHighlight(finalDocView.rootDoc); }; - const docView = getFirstDocView(targetDoc, originatingDoc); let annotatedDoc = Cast(targetDoc.annotationOn, Doc, null); + const contextDocs = docContext ? await DocListCastAsync(docContext.data) : undefined; + const contextDoc = contextDocs?.find(doc => Doc.AreProtosEqual(doc, targetDoc) || Doc.AreProtosEqual(doc, annotatedDoc)) ? docContext : undefined; + const targetDocContext = contextDoc || annotatedDoc; + const targetDocContextView = targetDocContext && getFirstDocView(targetDocContext); if (!docView && annotatedDoc && annotatedDoc !== originatingDoc?.context && targetDoc.type === DocumentType.TEXTANCHOR) { const first = getFirstDocView(annotatedDoc); if (first) { annotatedDoc = first.rootDoc; first.focus(targetDoc, false); } - } else if (docView) { // we have a docView already and aren't forced to create a new one ... just focus on the document. TODO move into view if necessary otherwise just highlight? - if (originatingDoc?.isPushpin) { - docView.props.focus(docView.rootDoc, willZoom, undefined, (didFocus: boolean) => { - if (!didFocus || docView.rootDoc.hidden) { - docView.rootDoc.hidden = !docView.rootDoc.hidden; - } - return focusAndFinish(); - }); - } - else { - docView.select(false); - docView.rootDoc.hidden && (docView.rootDoc.hidden = undefined); - // @ts-ignore - docView.props.focus(docView.rootDoc, willZoom, undefined, focusAndFinish); - } + } else if (docView && (targetDocContextView || !targetDocContext)) { // we have a docView already and aren't forced to create a new one ... just focus on the document. TODO move into view if necessary otherwise just highlight? + const first = annotatedDoc && getFirstDocView(annotatedDoc); + const targetFocus = (outFocus?: boolean) => docView.props.focus(docView.rootDoc, willZoom, undefined, (didFocus: boolean) => focusAndFinish(outFocus || didFocus)); + const annoFocus = (outFocus?: boolean) => first?.props.focus(first.rootDoc, false, undefined, (didFocus: boolean) => { + targetFocus(outFocus || didFocus); + return false; + }); + const contextFocus = targetDocContext === annotatedDoc ? undefined : (outFocus?: boolean) => targetDocContextView?.props.focus(targetDocContext, false, undefined, (didFocus: boolean) => { + annoFocus(outFocus || didFocus); + return false; + }); + (contextFocus || annoFocus || targetFocus)(); highlight(); } else { - const contextDocs = docContext ? await DocListCastAsync(docContext.data) : undefined; - const contextDoc = contextDocs?.find(doc => Doc.AreProtosEqual(doc, targetDoc) || Doc.AreProtosEqual(doc, annotatedDoc)) ? docContext : undefined; - const targetDocContext = contextDoc || annotatedDoc; - if (!targetDocContext) { // we don't have a view and there's no context specified ... create a new view of the target using the dockFunc or default createViewFunc(Doc.BrushDoc(targetDoc), finished); // bcz: should we use this?: Doc.MakeAlias(targetDoc))); highlight(); } else { // otherwise try to get a view of the context of the target - const targetDocContextView = getFirstDocView(targetDocContext); if (targetDocContextView) { // we found a context view and aren't forced to create a new one ... focus on the context first.. targetDocContext._viewTransition = "transform 500ms"; targetDocContextView.props.focus(targetDocContextView.rootDoc, willZoom); diff --git a/src/client/views/collections/TabDocView.tsx b/src/client/views/collections/TabDocView.tsx index 38e1551e6..e1e1c8656 100644 --- a/src/client/views/collections/TabDocView.tsx +++ b/src/client/views/collections/TabDocView.tsx @@ -356,7 +356,7 @@ export class TabDocView extends React.Component<TabDocViewProps> { </Tooltip> </>; } - focusFunc = (doc: Doc, willZoom?: boolean, scale?: number, afterFocus?: DocAfterFocusFunc, dontCenter?: boolean, notFocused?: boolean) => { + focusFunc = (doc: Doc, willZoom?: boolean, scale?: number, afterFocus?: DocAfterFocusFunc) => { if (!this.tab.header.parent._activeContentItem || this.tab.header.parent._activeContentItem !== this.tab.contentItem) { this.tab.header.parent.setActiveContentItem(this.tab.contentItem); // glr: Panning does not work when this is set - (this line is for trying to make a tab that is not topmost become topmost) } diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx index 68a65dfe7..6fdd569da 100644 --- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx +++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx @@ -907,53 +907,59 @@ export class CollectionFreeFormView extends CollectionSubView<PanZoomDocument, P } else { const layoutdoc = Doc.Layout(doc); const savedState = { px: NumCast(this.Document._panX), py: NumCast(this.Document._panY), s: this.Document[this.scaleFieldKey], pt: this.Document._viewTransition }; - const newState = HistoryUtil.getState(); - let newPanX = savedState.px; - let newPanY = savedState.py; + const { px, py } = layoutdoc.annotationOn ? savedState : willZoom ? this.setZoomToDoc(layoutdoc, scale) : this.setPanIntoView(doc); if (!layoutdoc.annotationOn) { // only pan and zoom to focus on a document if the document is not an annotation in an annotation overlay collection - willZoom && this.setScaleToZoom(layoutdoc, scale); - const cx = NumCast(this.props.Document._panX); - const cy = NumCast(this.props.Document._panY); - const pwid = this.props.PanelWidth() / NumCast(this.props.Document._viewScale, 1); - const phgt = this.props.PanelHeight() / NumCast(this.props.Document._viewScale, 1); - const screen = { left: cx - pwid / 2, right: cx + pwid / 2, top: cy - phgt / 2, bot: cy + phgt / 2 }; - const bounds = { left: NumCast(doc.x) - pwid / 10, right: NumCast(doc.x) + doc[WidthSym]() + pwid / 10, top: NumCast(doc.y) - phgt / 10, bot: NumCast(doc.y) + doc[HeightSym]() + phgt / 10 }; - newPanX = cx + Math.min(0, bounds.left - screen.left) + Math.max(0, bounds.right - screen.right); - newPanY = cy + Math.min(0, bounds.top - screen.top) + Math.max(0, bounds.bot - screen.bot); - newState.initializers![this.Document[Id]] = { panX: newPanX, panY: newPanY }; + newState.initializers![this.Document[Id]] = { panX: px, panY: py }; HistoryUtil.pushState(newState); } if (DocListCast(this.dataDoc[this.props.fieldKey]).includes(doc)) { // glr: freeform transform speed can be set by adjusting presTransition field - needs a way of knowing when presentation is not active... - if (!doc.z) this.setPan(newPanX, newPanY, doc.focusSpeed || doc.focusSpeed === 0 ? `transform ${doc.focusSpeed}ms` : "transform 500ms", true); // docs that are floating in their collection can't be panned to from their collection -- need to propagate the pan to a parent freeform somehow + if (!doc.z) this.setPan(px, py, doc.focusSpeed || doc.focusSpeed === 0 ? `transform ${doc.focusSpeed}ms` : "transform 500ms", true); // docs that are floating in their collection can't be panned to from their collection -- need to propagate the pan to a parent freeform somehow } Doc.BrushDoc(this.props.Document); - const newAfterFocus = (didFocus: boolean) => { - afterFocus && setTimeout(() => { - // @ts-ignore - if (afterFocus?.(didFocus || (newPanX !== savedState.px || newPanY !== savedState.py))) { + !doc.hidden && Doc.linkFollowHighlight(doc); + this.props.focus(this.props.Document, undefined, undefined, (didFocus: boolean) => { + setTimeout(() => { + if (afterFocus?.(didFocus || (px !== savedState.px || py !== savedState.py))) { this.Document._panX = savedState.px; this.Document._panY = savedState.py; this.Document[this.scaleFieldKey] = savedState.s; this.Document._viewTransition = savedState.pt; } doc.hidden && Doc.UnHighlightDoc(doc); - }, newPanX !== savedState.px || newPanY !== savedState.py ? 500 : 0); + }, px !== savedState.px || py !== savedState.py ? 500 : 0); return false; - }; - this.props.focus(this.props.Document, undefined, undefined, newAfterFocus); - !doc.hidden && Doc.linkFollowHighlight(doc); + }); } + } + setPanIntoView = (doc: Doc) => { + const cx = NumCast(this.props.Document._panX); + const cy = NumCast(this.props.Document._panY); + const pwid = this.props.PanelWidth() / NumCast(this.props.Document._viewScale, 1); + const phgt = this.props.PanelHeight() / NumCast(this.props.Document._viewScale, 1); + const screen = { left: cx - pwid / 2, right: cx + pwid / 2, top: cy - phgt / 2, bot: cy + phgt / 2 }; + const bounds = { left: NumCast(doc.x) - pwid / 10, right: NumCast(doc.x) + doc[WidthSym]() + pwid / 10, top: NumCast(doc.y) - phgt / 10, bot: NumCast(doc.y) + doc[HeightSym]() + phgt / 10 }; + return { + px: cx + Math.min(0, bounds.left - screen.left) + Math.max(0, bounds.right - screen.right), + py: cy + Math.min(0, bounds.top - screen.top) + Math.max(0, bounds.bot - screen.bot) + }; } - setScaleToZoom = (doc: Doc, scale: number = 0.75) => { - const pw = this.isAnnotationOverlay ? Doc.NativeWidth(this.props.Document) : this.props.PanelWidth(); - const ph = this.isAnnotationOverlay ? Doc.NativeHeight(this.props.Document) : this.props.PanelHeight(); + setZoomToDoc = (doc: Doc, scale: number = 0.75) => { + const pw = this.props.PanelWidth(); + const ph = this.props.PanelHeight(); pw && ph && (this.Document[this.scaleFieldKey] = scale * Math.min(pw / NumCast(doc._width), ph / NumCast(doc._height))); + const pwid = pw / NumCast(this.props.Document._viewScale, 1); + const phgt = ph / NumCast(this.props.Document._viewScale, 1); + const bounds = { left: NumCast(doc.x) - pwid / 10, right: NumCast(doc.x) + doc[WidthSym]() + pwid / 10, top: NumCast(doc.y) - phgt / 10, bot: NumCast(doc.y) + doc[HeightSym]() + phgt / 10 }; + return { + px: (bounds.left + bounds.right) / 2, + py: (bounds.top + bounds.bot) / 2 + }; } onChildClickHandler = () => this.props.childClickScript || ScriptCast(this.Document.onChildClick); diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx index a5698e138..d20866f94 100644 --- a/src/client/views/nodes/DocumentView.tsx +++ b/src/client/views/nodes/DocumentView.tsx @@ -41,7 +41,6 @@ import { PresBox } from './PresBox'; import { RadialMenu } from './RadialMenu'; import React = require("react"); import { LinkDocPreview } from "./LinkDocPreview"; -import { FormattedTextBoxComment } from "./formattedText/FormattedTextBoxComment"; export type DocAfterFocusFunc = (notFocused: boolean) => boolean; export type DocFocusFunc = (doc: Doc, willZoom?: boolean, scale?: number, afterFocus?: DocAfterFocusFunc) => void; @@ -919,8 +918,8 @@ export class DocumentView extends React.Component<DocumentViewProps> { toggleNativeDimensions = () => this.docView && Doc.toggleNativeDimensions(this.layoutDoc, this.docView.ContentScale, this.props.PanelWidth(), this.props.PanelHeight()); contentsActive = () => this.docView?.contentsActive(); - focus = (doc: Doc, willZoom?: boolean, scale?: number, afterFocus?: DocAfterFocusFunc, focused?: boolean) => { - return this.docView?.focus(doc, willZoom, scale, afterFocus, focused); + focus = (doc: Doc, willZoom?: boolean, scale?: number, afterFocus?: DocAfterFocusFunc) => { + return this.docView?.focus(doc, willZoom, scale, afterFocus); } getBounds = () => { if (!this.docView || !this.docView.ContentDiv || this.docView.props.renderDepth === 0 || this.docView.props.treeViewDoc || Doc.AreProtosEqual(this.props.Document, Doc.UserDoc())) { diff --git a/src/client/views/nodes/WebBox.tsx b/src/client/views/nodes/WebBox.tsx index d3d58b2f8..ef0df25b6 100644 --- a/src/client/views/nodes/WebBox.tsx +++ b/src/client/views/nodes/WebBox.tsx @@ -4,7 +4,7 @@ import { action, computed, IReactionDisposer, observable, reaction, runInAction import { observer } from "mobx-react"; import { Dictionary } from "typescript-collections"; import * as WebRequest from 'web-request'; -import { Doc, DocListCast, HeightSym, WidthSym, Opt } from "../../../fields/Doc"; +import { Doc, DocListCast, HeightSym, Opt, WidthSym } from "../../../fields/Doc"; import { documentSchema } from "../../../fields/documentSchemas"; import { Id } from "../../../fields/FieldSymbols"; import { HtmlField } from "../../../fields/HtmlField"; @@ -26,10 +26,10 @@ import { ViewBoxAnnotatableComponent } from "../DocComponent"; import { DocumentDecorations } from "../DocumentDecorations"; import { MarqueeAnnotator } from "../MarqueeAnnotator"; import { Annotation } from "../pdf/Annotation"; +import { DocAfterFocusFunc } from "./DocumentView"; import { FieldView, FieldViewProps } from './FieldView'; import "./WebBox.scss"; import React = require("react"); -import { DocFocusFunc, DocAfterFocusFunc, DocumentView } from "./DocumentView"; const htmlToText = require("html-to-text"); type WebDocument = makeInterface<[typeof documentSchema]>; |