aboutsummaryrefslogtreecommitdiff
path: root/src/client/views/collections/TabDocView.tsx
diff options
context:
space:
mode:
authorNaafiyan Ahmed <naafiyan@gmail.com>2022-06-09 12:46:25 -0400
committerNaafiyan Ahmed <naafiyan@gmail.com>2022-06-09 12:46:25 -0400
commit7d38e4a98a0382cdd032d63d375707f19362873d (patch)
tree415273805b218e07a4ad9e4c547e26469c4b0e13 /src/client/views/collections/TabDocView.tsx
parent9de05a8fc6d1cda01662f9bce3a5f6764d280be3 (diff)
parent331cb0bec8089c4435126542ed3181fe227eff51 (diff)
cleaned up code in InkTranscription
Diffstat (limited to 'src/client/views/collections/TabDocView.tsx')
-rw-r--r--src/client/views/collections/TabDocView.tsx158
1 files changed, 107 insertions, 51 deletions
diff --git a/src/client/views/collections/TabDocView.tsx b/src/client/views/collections/TabDocView.tsx
index 2b78b20ea..142013d1a 100644
--- a/src/client/views/collections/TabDocView.tsx
+++ b/src/client/views/collections/TabDocView.tsx
@@ -4,15 +4,15 @@ import { Tooltip } from '@material-ui/core';
import 'golden-layout/src/css/goldenlayout-base.css';
import 'golden-layout/src/css/goldenlayout-dark-theme.css';
import { clamp } from 'lodash';
-import { action, computed, IReactionDisposer, observable, reaction, runInAction } from "mobx";
+import { action, computed, IReactionDisposer, observable, reaction } from "mobx";
import { observer } from "mobx-react";
import * as ReactDOM from 'react-dom';
-import { DataSym, Doc, DocListCast, DocListCastAsync, HeightSym, Opt, WidthSym } from "../../../fields/Doc";
+import { DataSym, Doc, HeightSym, Opt, WidthSym } from "../../../fields/Doc";
import { Id } from '../../../fields/FieldSymbols';
import { List } from '../../../fields/List';
import { FieldId } from "../../../fields/RefField";
import { BoolCast, Cast, NumCast, StrCast } from "../../../fields/Types";
-import { emptyFunction, lightOrDark, returnEmptyDoclist, returnFalse, returnTrue, setupMoveUpEvents, Utils } from "../../../Utils";
+import { emptyFunction, lightOrDark, returnEmptyDoclist, returnFalse, returnTrue, setupMoveUpEvents, simulateMouseClick, Utils } from "../../../Utils";
import { DocServer } from "../../DocServer";
import { DocUtils } from '../../documents/Documents';
import { DocumentType } from '../../documents/DocumentTypes';
@@ -27,14 +27,16 @@ import { Colors, Shadows } from '../global/globalEnums';
import { LightboxView } from '../LightboxView';
import { MainView } from '../MainView';
import { DocFocusOptions, DocumentView, DocumentViewProps } from "../nodes/DocumentView";
+import { DashFieldView } from '../nodes/formattedText/DashFieldView';
import { PinProps, PresBox, PresMovement } from '../nodes/trails';
import { DefaultStyleProvider, StyleProp } from '../StyleProvider';
import { CollectionDockingView } from './CollectionDockingView';
-import { CollectionDockingViewMenu } from './CollectionDockingViewMenu';
import { CollectionFreeFormView } from './collectionFreeForm/CollectionFreeFormView';
import { CollectionView, CollectionViewType } from './CollectionView';
import "./TabDocView.scss";
import React = require("react");
+import { listSpec } from '../../../fields/Schema';
+import { ScriptField } from '../../../fields/ScriptField';
const _global = (window /* browser */ || global /* node */) as any;
interface TabDocViewProps {
@@ -66,6 +68,8 @@ export class TabDocView extends React.Component<TabDocViewProps> {
get stack() { return (this.props as any).glContainer.parent.parent; }
get tab() { return (this.props as any).glContainer.tab; }
get view() { return this._view; }
+ _lastTab: any;
+ _lastView: DocumentView | undefined;
@action
init = (tab: any, doc: Opt<Doc>) => {
@@ -74,14 +78,12 @@ export class TabDocView extends React.Component<TabDocViewProps> {
tab._disposers = {} as { [name: string]: IReactionDisposer };
tab.contentItem.config.fixed && (tab.contentItem.parent.config.fixed = true);
tab.DashDoc = doc;
- CollectionDockingView.Instance.tabMap.add(tab);
const iconType: IconProp = Doc.toIcon(doc);
// setup the title element and set its size according to the # of chars in the title. Show the full title when clicked.
const titleEle = tab.titleElement[0];
const iconWrap = document.createElement("div");
const closeWrap = document.createElement("div");
-
titleEle.size = StrCast(doc.title).length + 3;
titleEle.value = doc.title;
titleEle.onkeydown = (e: KeyboardEvent) => {
@@ -92,14 +94,28 @@ export class TabDocView extends React.Component<TabDocViewProps> {
Doc.GetProto(doc).title = e.currentTarget.value;
}));
- const dragBtnDown = (e: React.PointerEvent) => {
- setupMoveUpEvents(this, e, e => !e.defaultPrevented && DragManager.StartDocumentDrag([iconWrap], new DragManager.DocumentDragData([doc], doc.dropAction as dropActionType), e.clientX, e.clientY), returnFalse, emptyFunction);
- };
-
-
if (tab.element[0].children[1].children.length === 1) {
- iconWrap.className = "lm_iconWrap";
- iconWrap.id = "lm_iconWrap";
+ iconWrap.className = "lm_iconWrap lm_moreInfo";
+ const dragBtnDown = (e: React.PointerEvent) => {
+ setupMoveUpEvents(this, e, e => !e.defaultPrevented && DragManager.StartDocumentDrag([iconWrap], new DragManager.DocumentDragData([doc], doc.dropAction as dropActionType), e.clientX, e.clientY), returnFalse, action(e => {
+ if (this.view) {
+ SelectionManager.SelectView(this.view, false);
+ let child = this.view.ContentDiv!.children[0];
+ while (child.children.length) {
+ const next = Array.from(child.children).find(c => c.className?.toString().includes("SVGAnimatedString") || typeof (c.className) === "string");
+ if (next?.className?.toString().includes(DocumentView.ROOT_DIV)) break;
+ if (next?.className?.toString().includes(DashFieldView.name)) break;
+ if (next) child = next;
+ else break;
+ }
+ simulateMouseClick(child, e.clientX, e.clientY + 30, e.screenX, e.screenY + 30);
+ }
+ else { this._activated = true;
+ setTimeout(() =>this.view && SelectionManager.SelectView(this.view, false));
+ }
+ }));
+ };
+
closeWrap.className = "lm_iconWrap";
closeWrap.id = "lm_closeWrap";
closeWrap.onclick = (e: MouseEvent) => {
@@ -111,6 +127,7 @@ export class TabDocView extends React.Component<TabDocViewProps> {
const closeIcon = <FontAwesomeIcon icon={"times"} />;
ReactDOM.render(docIcon, iconWrap);
ReactDOM.render(closeIcon, closeWrap);
+ tab.reactComponents = [iconWrap, closeWrap];
// tab.element[0].append(closeWrap);
tab.element[0].prepend(iconWrap);
tab._disposers.layerDisposer = reaction(() => ({ layer: tab.DashDoc.activeLayer, color: this.tabColor }),
@@ -122,7 +139,6 @@ export class TabDocView extends React.Component<TabDocViewProps> {
titleEle.style.backgroundColor = "transparent";
iconWrap.style.color = textColor;
closeWrap.style.color = textColor;
- moreInfoDrag.style.backgroundColor = textColor;
tab.element[0].style.background = !layer ? color : "dimgrey";
}, { fireImmediately: true });
}
@@ -155,19 +171,6 @@ export class TabDocView extends React.Component<TabDocViewProps> {
// toggle.style.textTransform = selected ? "uppercase" : "";
}));
- //attach the selection doc buttons menu to the drag handle
- const stack: HTMLDivElement = tab.contentItem.parent;
- const header: HTMLDivElement = tab;
- stack.onscroll = action((e: any) => {
- console.log('scrolling...');
- });
- const moreInfoDrag = document.createElement("div");
- moreInfoDrag.className = "lm_iconWrap";
- tab._disposers.buttonDisposer = reaction(() => this.view, view =>
- view && [ReactDOM.render(<span><CollectionDockingViewMenu views={() => [view]} Stack={stack} /></span>, moreInfoDrag), tab._disposers.buttonDisposer?.()],
- { fireImmediately: true });
- // tab.reactComponents = [moreInfoDrag];
- // tab.element[0].children[3].before(moreInfoDrag);
// highlight the tab when the tab document is brushed in any part of the UI
tab._disposers.reactionDisposer = reaction(() => ({ title: doc.title, degree: Doc.IsBrushedDegree(doc) }), ({ title, degree }) => {
@@ -190,13 +193,15 @@ export class TabDocView extends React.Component<TabDocViewProps> {
* Adds a document to the presentation view
**/
@action
- public static async PinDoc(doc: Doc, pinProps?: PinProps) {
- if (pinProps?.unpin) console.log('TODO: Remove UNPIN from this location');
- //add this new doc to props.Document
+ public static PinDoc(docs: Doc|Doc[], pinProps?: PinProps) {
+ const docList = ((docs instanceof Doc) ? [docs]: docs);
+ const batch = UndoManager.StartBatch("pinning doc");
+
+ // all docs will be added to the ActivePresentation as stored on CurrentUserUtils
const curPres = CurrentUserUtils.ActivePresentation;
- if (curPres) {
+ curPres && docList.forEach(doc => {
+ // Edge Case 1: Cannot pin document to itself
if (doc === curPres) { alert("Cannot pin presentation document to itself"); return; }
- const batch = UndoManager.StartBatch("pinning doc");
const pinDoc = Doc.MakeAlias(doc);
pinDoc.presentationTargetDoc = doc;
pinDoc.title = doc.title + " - Slide";
@@ -216,6 +221,48 @@ export class TabDocView extends React.Component<TabDocViewProps> {
const size: number = PresBox.Instance?._selectedArray.size;
const presSelected: Doc | undefined = presArray && size ? presArray[size - 1] : undefined;
const duration = NumCast(doc[`${Doc.LayoutFieldKey(pinDoc)}-duration`], null);
+ // If pinWithView option set then update scale and x / y props of slide
+ if (pinProps?.pinWithView) {
+ const viewProps = pinProps.pinWithView;
+ pinDoc.presPinView = true;
+ pinDoc.presPinViewX = viewProps.bounds.left + viewProps.bounds.width / 2;
+ pinDoc.presPinViewY = viewProps.bounds.top + viewProps.bounds.height / 2;
+ pinDoc.presPinViewScale = viewProps.scale;
+ pinDoc.contentBounds = new List<number>([viewProps.bounds.left, viewProps.bounds.top, viewProps.bounds.left+viewProps.bounds.width, viewProps.bounds.top+viewProps.bounds.height]);
+ }
+ if (pinProps?.pinDocView) {
+ const scrollable = [DocumentType.PDF, DocumentType.RTF, DocumentType.WEB].includes(pinDoc.type as any) || pinDoc._viewType === CollectionViewType.Stacking;
+ const pannable: boolean = ((pinDoc.type === DocumentType.COL && doc._viewType === CollectionViewType.Freeform) || doc.type === DocumentType.IMG);
+ if (scrollable) {
+ const scroll = doc._scrollTop;
+ pinDoc.presPinView = true;
+ pinDoc.presPinViewScroll = scroll;
+ } else if ([DocumentType.AUDIO, DocumentType.VID].includes(doc.type as any)) {
+ pinDoc.presPinView = true;
+ pinDoc.presStartTime = doc._currentTimecode;
+ pinDoc.presEndTime = NumCast(doc._currentTimecode) + 0.1;
+ } else if (pannable) {
+ pinDoc.presPinView = true;
+ pinDoc.presPinViewX = pinDoc._panX;
+ pinDoc.presPinViewY = pinDoc._panY;
+ pinDoc.presPinViewScale = pinDoc._viewScale;
+ const pw = NumCast(pinProps.panelWidth);
+ const ph = NumCast(pinProps.panelHeight);
+ const ps = NumCast(pinDoc._viewScale);
+ if (pw && ph && ps) {
+ pinDoc.contentBounds = new List<number>([
+ NumCast(pinDoc.panX)-pw/2/ps,
+ NumCast(pinDoc.panY)-ph/2/ps,
+ NumCast(pinDoc.panX)+pw/2/ps,
+ NumCast(pinDoc.panY)+ph/2/ps]);
+ }
+ } else if (doc.type === DocumentType.COMPARISON) {
+ const width = doc._clipWidth;
+ pinDoc.presPinClipWidth = width;
+ pinDoc.presPinView = true;
+ }
+ }
+ pinDoc.onClick = ScriptField.MakeFunction("navigateToDoc(self.presentationTargetDoc, self)");
Doc.AddDocToList(curPres, "data", pinDoc, presSelected);
if (!pinProps?.audioRange && duration !== undefined) {
pinDoc.mediaStart = "manual";
@@ -234,22 +281,16 @@ export class TabDocView extends React.Component<TabDocViewProps> {
pinDoc.presMovement = PresMovement.None;
}
if (curPres.expandBoolean) pinDoc.presExpandInlineButton = true;
- const dview = CollectionDockingView.Instance.props.Document;
- const fieldKey = CollectionDockingView.Instance.props.fieldKey;
- const sublists = DocListCast(dview[fieldKey]);
- const tabs = Cast(sublists[0], Doc, null);
- const tabdocs = await DocListCastAsync(tabs?.data);
- runInAction(() => {
- if (!pinProps?.hidePresBox && !tabdocs?.includes(curPres)) {
- tabdocs?.push(curPres); // bcz: Argh! this is annoying. if multiple documents are pinned, this will get called multiple times before the presentation view is drawn. Thus it won't be in the tabdocs list and it will get created multple times. so need to explicilty add the presbox to the list of open tabs
- CollectionDockingView.AddSplit(curPres, "right");
- }
- PresBox.Instance?._selectedArray.clear();
- pinDoc && PresBox.Instance?._selectedArray.set(pinDoc, undefined); //Update selected array
- DocumentManager.Instance.jumpToDocument(doc, false, undefined, []);
- batch.end();
- });
+ PresBox.Instance?._selectedArray.clear();
+ pinDoc && PresBox.Instance?._selectedArray.set(pinDoc, undefined); //Update selected array
+ });
+ if (!Array.from(CollectionDockingView.Instance.tabMap).map(d => d.DashDoc).includes(curPres)) {
+ const docs = Cast(Cast(Doc.UserDoc().myOverlayDocs, Doc, null).data, listSpec(Doc), []);
+ if (docs.includes(curPres)) docs.splice(docs.indexOf(curPres), 1);
+ CollectionDockingView.AddSplit(curPres, "right");
+ setTimeout(() => DocumentManager.Instance.jumpToDocument(docList.lastElement(), false, undefined, []), 100); // keeps the pinned doc in view since the sidebar shifts things
}
+ setTimeout(batch.end, 500); // need to wait until dockingview (goldenlayout) updates all its structurs
}
componentDidMount() {
@@ -265,10 +306,13 @@ export class TabDocView extends React.Component<TabDocViewProps> {
// ({ selected, title }) => title && (title.style.backgroundColor = selected ? "white" : ""),
// { fireImmediately: true });
}
+ componentDidUpdate() {
+ this._view && DocumentManager.Instance.AddView(this._view);
+ }
componentWillUnmount() {
this._tabReaction?.();
- this.tab && CollectionDockingView.Instance.tabMap.delete(this.tab);
+ this._view && DocumentManager.Instance.RemoveView(this._view);
this.props.glContainer.layoutManager.off("activeContentItemChanged", this.onActiveContentItemChanged);
}
@@ -297,7 +341,11 @@ export class TabDocView extends React.Component<TabDocViewProps> {
case "close": return CollectionDockingView.CloseSplit(doc, locationParams);
case "fullScreen": return CollectionDockingView.OpenFullScreen(doc);
case "replace": return CollectionDockingView.ReplaceTab(doc, locationParams, this.stack);
- case "lightbox": return LightboxView.AddDocTab(doc, location);
+ // case "lightbox": {
+ // // TabDocView.PinDoc(doc, { hidePresBox: true });
+ // return LightboxView.AddDocTab(doc, location, undefined, this.addDocTab);
+ // }
+ case "lightbox": return LightboxView.AddDocTab(doc, location, undefined, this.addDocTab);
case "toggle": return CollectionDockingView.ToggleSplit(doc, locationParams, this.stack);
case "inPlace":
case "add":
@@ -351,7 +399,11 @@ export class TabDocView extends React.Component<TabDocViewProps> {
@computed get docView() {
return !this._activated || !this._document || this._document._viewType === CollectionViewType.Docking ? (null) :
- <><DocumentView key={this._document[Id]} ref={action((r: DocumentView) => this._view = r)}
+ <><DocumentView key={this._document[Id]} ref={action((r: DocumentView) => {
+ this._lastView && DocumentManager.Instance.RemoveView(this._lastView);
+ this._view = r;
+ this._lastView = this._view;
+ })}
renderDepth={0}
Document={this._document}
DataDoc={!Doc.AreProtosEqual(this._document[DataSym], this._document) ? this._document[DataSym] : undefined}
@@ -407,6 +459,10 @@ export class TabDocView extends React.Component<TabDocViewProps> {
height: "100%", width: "100%"
}} ref={ref => {
if (this._mainCont = ref) {
+ if (this._lastTab) {
+ this._view && DocumentManager.Instance.RemoveView(this._view);
+ }
+ this._lastTab = this.tab;
(this._mainCont as any).InitTab = (tab: any) => this.init(tab, this._document);
DocServer.GetRefField(this.props.documentId).then(action(doc => doc instanceof Doc && (this._document = doc) && this.tab && this.init(this.tab, this._document)));
new _global.ResizeObserver(action((entries: any) => this._forceInvalidateScreenToLocal++)).observe(ref);
@@ -517,7 +573,7 @@ export class TabMinimapView extends React.Component<TabMinimapViewProps> {
docFilters={CollectionDockingView.Instance.childDocFilters}
docRangeFilters={CollectionDockingView.Instance.childDocRangeFilters}
searchFilterDocs={CollectionDockingView.Instance.searchFilterDocs}
- fitContentsToDoc={returnTrue}
+ fitContentsToBox={returnTrue}
/>
<div className="miniOverlay" onPointerDown={this.miniDown} >
<div className="miniThumb" style={{ width: `${miniWidth}% `, height: `${miniHeight}% `, left: `${miniLeft}% `, top: `${miniTop}% `, }} />