aboutsummaryrefslogtreecommitdiff
path: root/src/client/views/nodes/trails
diff options
context:
space:
mode:
authorbobzel <zzzman@gmail.com>2023-02-27 15:08:45 -0500
committerbobzel <zzzman@gmail.com>2023-02-27 15:08:45 -0500
commitaf2a2c83868c87812e9ae54c8e3cced81374619a (patch)
treedaa3f79b93c22f9c0f90b00c2e6f843de6eedc36 /src/client/views/nodes/trails
parent536e1ed3f847b0e7343c1cf9eb7fc0c97818e171 (diff)
restructured getAnchor()/scrollFocus to be more consistent. added setterscript for computedFields. restructed getFieldsImpl to avoid making multiple requests for the same document due to timing issues by 'locking' a document cache with a promise before sending the server request. added rotation and fill color as animatable fields. fixed image cropping for
Diffstat (limited to 'src/client/views/nodes/trails')
-rw-r--r--src/client/views/nodes/trails/PresBox.tsx211
1 files changed, 145 insertions, 66 deletions
diff --git a/src/client/views/nodes/trails/PresBox.tsx b/src/client/views/nodes/trails/PresBox.tsx
index 13cbd87eb..45d386436 100644
--- a/src/client/views/nodes/trails/PresBox.tsx
+++ b/src/client/views/nodes/trails/PresBox.tsx
@@ -4,9 +4,9 @@ import { Tooltip } from '@material-ui/core';
import { action, computed, IReactionDisposer, observable, ObservableSet, reaction, runInAction } from 'mobx';
import { observer } from 'mobx-react';
import { ColorState, SketchPicker } from 'react-color';
-import { AnimationSym, Doc, DocListCast, FieldResult, Opt, StrListCast } from '../../../../fields/Doc';
+import { AnimationSym, Doc, DocListCast, Field, FieldResult, Opt, StrListCast } from '../../../../fields/Doc';
import { Copy, Id } from '../../../../fields/FieldSymbols';
-import { InkTool } from '../../../../fields/InkField';
+import { InkField, InkTool } from '../../../../fields/InkField';
import { List } from '../../../../fields/List';
import { ObjectField } from '../../../../fields/ObjectField';
import { listSpec } from '../../../../fields/Schema';
@@ -34,8 +34,23 @@ import { FieldView, FieldViewProps } from '../FieldView';
import { ScriptingBox } from '../ScriptingBox';
import './PresBox.scss';
import { PresEffect, PresEffectDirection, PresMovement, PresStatus } from './PresEnums';
+import { SerializationHelper } from '../../../util/SerializationHelper';
const { Howl } = require('howler');
+export interface pinDataTypes {
+ scrollable?: boolean;
+ pannable?: boolean;
+ viewType?: boolean;
+ inkable?: boolean;
+ filters?: boolean;
+ pivot?: boolean;
+ temporal?: boolean;
+ clippable?: boolean;
+ dataview?: boolean;
+ textview?: boolean;
+ poslayoutview?: boolean;
+ dataannos?: boolean;
+}
export interface PinProps {
audioRange?: boolean;
activeFrame?: number;
@@ -45,18 +60,7 @@ export interface PinProps {
pinDocLayout?: boolean; // pin layout info (width/height/x/y)
pinDocContent?: boolean; // pin data info (scroll/pan/zoom/text)
pinAudioPlay?: boolean; // pin audio annotation
- pinData?: {
- scrollable?: boolean | undefined;
- pannable?: boolean | undefined;
- viewType?: boolean | undefined;
- filters?: boolean | undefined;
- temporal?: boolean | undefined;
- clippable?: boolean | undefined;
- dataview?: boolean | undefined;
- textview?: boolean | undefined;
- poslayoutview?: boolean | undefined;
- dataannos?: boolean | undefined;
- };
+ pinData?: pinDataTypes;
}
@observer
@@ -318,19 +322,9 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() {
this.onHideDocument(); //Handles hide after/before
}
});
- static pinDataTypes(target?: Doc): {
- scrollable?: boolean;
- pannable?: boolean;
- viewType?: boolean;
- filters?: boolean;
- temporal?: boolean;
- clippable?: boolean;
- dataview?: boolean;
- textview?: boolean;
- poslayoutview?: boolean;
- dataannos?: boolean;
- } {
+ static pinDataTypes(target?: Doc): pinDataTypes {
const targetType = target?.type as any;
+ const inkable = [DocumentType.INK].includes(targetType);
const scrollable = [DocumentType.PDF, DocumentType.RTF, DocumentType.WEB].includes(targetType) || target?._viewType === CollectionViewType.Stacking;
const pannable = [DocumentType.IMG, DocumentType.PDF].includes(targetType) || (targetType === DocumentType.COL && target?._viewType === CollectionViewType.Freeform);
const temporal = [DocumentType.AUDIO, DocumentType.VID].includes(targetType);
@@ -340,18 +334,19 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() {
const textview = [DocumentType.RTF].includes(targetType) && target?.activeFrame === undefined;
const viewType = targetType === DocumentType.COL;
const filters = true;
+ const pivot = true;
const dataannos = false;
- return { scrollable, pannable, viewType, filters, temporal, clippable, dataview, textview, poslayoutview, dataannos };
+ return { scrollable, pannable, inkable, viewType, pivot, filters, temporal, clippable, dataview, textview, poslayoutview, dataannos };
}
@action
playAnnotation = (anno: AudioField) => {};
@action
- static restoreTargetDocView(bestTargetView: Opt<DocumentView>, pinProps: PinProps | undefined, activeItem: Doc, transTime: number, pinDataTypes = this.pinDataTypes(bestTargetView?.rootDoc)) {
- if (!bestTargetView) return;
- const bestTarget = bestTargetView.rootDoc;
+ static restoreTargetDocView(bestTargetView: Opt<DocumentView>, activeItem: Doc, transTime: number, pinDocLayout: boolean = BoolCast(activeItem.presPinLayout), pinDataTypes?: pinDataTypes, targetDoc?: Doc) {
+ const bestTarget = bestTargetView?.rootDoc ?? (targetDoc?.unrendered ? DocCast(targetDoc?.annotationOn) : targetDoc);
+ if (!bestTarget) return;
let changed = false;
- if (pinProps?.pinDocLayout) {
+ if (pinDocLayout) {
if (
bestTarget.x !== NumCast(activeItem.presX, NumCast(bestTarget.x)) ||
bestTarget.y !== NumCast(activeItem.presY, NumCast(bestTarget.y)) ||
@@ -369,33 +364,51 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() {
changed = true;
}
}
- if (pinDataTypes.clippable) {
+ if (pinDataTypes?.clippable || (!pinDataTypes && activeItem.presPinClipWidth !== undefined)) {
if (bestTarget._clipWidth !== activeItem.presPinClipWidth) {
bestTarget._clipWidth = activeItem.presPinClipWidth;
changed = true;
}
}
- if (pinDataTypes.temporal) {
+ if (pinDataTypes?.temporal || (!pinDataTypes && activeItem.presStartTime !== undefined)) {
if (bestTarget._currentTimecode !== activeItem.presStartTime) {
bestTarget._currentTimecode = activeItem.presStartTime;
changed = true;
}
}
- if (pinDataTypes.viewType && activeItem.presPinViewType !== undefined) {
+ if (pinDataTypes?.inkable || (!pinDataTypes && (activeItem.presFillColor !== undefined || activeItem.color !== undefined))) {
+ if (bestTarget.fillColor !== activeItem.presFillColor) {
+ Doc.GetProto(bestTarget).fillColor = activeItem.presFillColor;
+ changed = true;
+ }
+ if (bestTarget.color !== activeItem.color) {
+ Doc.GetProto(bestTarget).color = activeItem.color;
+ changed = true;
+ }
+ }
+ if ((pinDataTypes?.viewType && activeItem.presPinViewType !== undefined) || (!pinDataTypes && activeItem.presPinViewType !== undefined)) {
if (bestTarget._viewType !== activeItem.presPinViewType) {
bestTarget._viewType = activeItem.presPinViewType;
changed = true;
}
}
- if (pinDataTypes.filters && activeItem.presPinDocFilters !== undefined) {
+ if ((pinDataTypes?.filters && activeItem.presPinDocFilters !== undefined) || (!pinDataTypes && activeItem.presPinDocFilters !== undefined)) {
if (bestTarget.docFilters !== activeItem.presPinDocFilters) {
bestTarget.docFilters = ObjectField.MakeCopy(activeItem.presPinDocFilters as ObjectField) || new List<string>([]);
changed = true;
}
}
- if (pinDataTypes.scrollable) {
+ if ((pinDataTypes?.pivot && activeItem.presPinPvitoField !== undefined) || (!pinDataTypes && activeItem.presPinPivotField !== undefined)) {
+ if (bestTarget.pivotField !== activeItem.presPinPivotField) {
+ bestTarget.pivotField = activeItem.presPinPivotField;
+ bestTarget._prevFilterIndex = 1; // need to revisit this...see CollectionTimeView
+ changed = true;
+ }
+ }
+
+ if (pinDataTypes?.scrollable || (!pinDataTypes && activeItem.presPinViewScroll !== undefined)) {
if (bestTarget._scrollTop !== activeItem.presPinViewScroll) {
bestTarget._scrollTop = activeItem.presPinViewScroll;
changed = true;
@@ -406,39 +419,59 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() {
}
}
}
- if (pinDataTypes.dataannos) {
+ if (pinDataTypes?.dataannos || (!pinDataTypes && activeItem.presAnnotations !== undefined)) {
const fkey = Doc.LayoutFieldKey(bestTarget);
- Doc.GetProto(bestTarget)[fkey + '-annotations'] = new List<Doc>([...DocListCast(bestTarget[fkey + '-annotations']).filter(doc => doc.unrendered), ...DocListCast(activeItem.presAnnotations)]);
+ const oldItems = DocListCast(bestTarget[fkey + '-annotations']).filter(doc => doc.unrendered);
+ const newItems = DocListCast(activeItem.presAnnotations).map(doc => {
+ doc.hidden = false;
+ return doc;
+ });
+ const hiddenItems = DocListCast(bestTarget[fkey + '-annotations'])
+ .filter(doc => !doc.unrendered && !newItems.includes(doc))
+ .map(doc => {
+ doc.hidden = true;
+ return doc;
+ });
+ const newList = new List<Doc>([...oldItems, ...hiddenItems, ...newItems]);
+ Doc.GetProto(bestTarget)[fkey + '-annotations'] = newList;
}
- if (pinDataTypes.dataview && activeItem.presData !== undefined) {
+ if ((pinDataTypes?.dataview && activeItem.presData !== undefined) || (!pinDataTypes && activeItem.presData !== undefined)) {
bestTarget._dataTransition = `all ${transTime}ms`;
const fkey = Doc.LayoutFieldKey(bestTarget);
Doc.GetProto(bestTarget)[fkey] = activeItem.presData instanceof ObjectField ? activeItem.presData[Copy]() : activeItem.presData;
bestTarget[fkey + '-useAlt'] = activeItem.presUseAlt;
setTimeout(() => (bestTarget._dataTransition = undefined), transTime + 10);
}
- if (pinDataTypes.textview && activeItem.presData !== undefined) Doc.GetProto(bestTarget)[Doc.LayoutFieldKey(bestTarget)] = activeItem.presData instanceof ObjectField ? activeItem.presData[Copy]() : activeItem.presData;
- if (pinDataTypes.poslayoutview) {
+ if ((pinDataTypes?.textview && activeItem.presData !== undefined) || (!pinDataTypes && activeItem.presData !== undefined)) {
+ Doc.GetProto(bestTarget)[Doc.LayoutFieldKey(bestTarget)] = activeItem.presData instanceof ObjectField ? activeItem.presData[Copy]() : activeItem.presData;
+ }
+ if (pinDataTypes?.poslayoutview || (!pinDataTypes && activeItem.presPinLayoutData !== undefined)) {
changed = true;
+ const layoutField = Doc.LayoutFieldKey(bestTarget);
+ const transitioned = new Set<Doc>();
StrListCast(activeItem.presPinLayoutData)
- .map(str => JSON.parse(str) as { id: string; x: number; y: number; w: number; h: number })
- .forEach(data => {
- const doc = DocServer.GetCachedRefField(data.id) as Doc;
- doc._dataTransition = `all ${transTime}ms`;
- doc.x = data.x;
- doc.y = data.y;
- doc._width = data.w;
- doc._height = data.h;
+ .map(str => JSON.parse(str) as { id: string; x: number; y: number; back: string; fill: string; w: number; h: number; data: string; text: string })
+ .forEach(async data => {
+ const doc = DocCast(DocServer.GetCachedRefField(data.id));
+ if (doc) {
+ transitioned.add(doc);
+ const field = !data.data ? undefined : await SerializationHelper.Deserialize(data.data);
+ const tfield = !data.text ? undefined : await SerializationHelper.Deserialize(data.text);
+ doc._dataTransition = `all ${transTime}ms`;
+ doc.x = data.x;
+ doc.y = data.y;
+ data.back && (doc._backgroundColor = data.back);
+ data.fill && (doc._fillColor = data.fill);
+ doc._width = data.w;
+ doc._height = data.h;
+ data.data && (Doc.GetProto(doc).data = field);
+ data.text && (Doc.GetProto(doc).text = tfield);
+ Doc.AddDocToList(Doc.GetProto(bestTarget), layoutField, doc);
+ }
});
- setTimeout(
- () =>
- StrListCast(activeItem.presPinLayoutData)
- .map(str => JSON.parse(str) as { id: string; x: number; y: number; w: number; h: number })
- .forEach(action(data => ((DocServer.GetCachedRefField(data.id) as Doc)._dataTransition = undefined))),
- transTime + 10
- );
+ setTimeout(() => Array.from(transitioned).forEach(action(doc => (doc._dataTransition = undefined))), transTime + 10);
}
- if (pinDataTypes.pannable) {
+ if (pinDataTypes?.pannable || (!pinDataTypes && (activeItem.presPinViewBounds !== undefined || activeItem.presPinViewX !== undefined || activeItem.presPinViewScale !== undefined))) {
const contentBounds = Cast(activeItem.presPinViewBounds, listSpec('number'));
if (contentBounds) {
const viewport = { panX: (contentBounds[0] + contentBounds[2]) / 2, panY: (contentBounds[1] + contentBounds[3]) / 2, width: contentBounds[2] - contentBounds[0], height: contentBounds[3] - contentBounds[1] };
@@ -460,7 +493,7 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() {
}
}
if (changed) {
- return bestTargetView.setViewTransition('all', transTime);
+ return bestTargetView?.setViewTransition('all', transTime);
}
}
@@ -499,12 +532,31 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() {
pinDoc.presAnnotations = new List<Doc>(DocListCast(Doc.GetProto(targetDoc)[fkey + '-annotations']).filter(doc => !doc.unrendered));
}
if (pinProps.pinData.textview) pinDoc.presData = targetDoc[Doc.LayoutFieldKey(targetDoc)] instanceof ObjectField ? (targetDoc[Doc.LayoutFieldKey(targetDoc)] as ObjectField)[Copy]() : targetDoc.text;
+ if (pinProps.pinData.inkable) {
+ pinDoc.presFillColor = targetDoc.fillColor;
+ pinDoc.presColor = targetDoc.color;
+ }
if (pinProps.pinData.scrollable) pinDoc.presPinViewScroll = targetDoc._scrollTop;
if (pinProps.pinData.clippable) pinDoc.presPinClipWidth = targetDoc._clipWidth;
if (pinProps.pinData.poslayoutview)
- pinDoc.presPinLayoutData = new List<string>(DocListCast(targetDoc[fkey] as ObjectField).map(d => JSON.stringify({ id: d[Id], x: NumCast(d.x), y: NumCast(d.y), w: NumCast(d._width), h: NumCast(d._height) })));
+ pinDoc.presPinLayoutData = new List<string>(
+ DocListCast(targetDoc[fkey] as ObjectField).map(d =>
+ JSON.stringify({
+ id: d[Id],
+ x: NumCast(d.x),
+ y: NumCast(d.y),
+ w: NumCast(d._width),
+ h: NumCast(d._height),
+ fill: StrCast(d._fillColor),
+ back: StrCast(d._backgroundColor),
+ data: SerializationHelper.Serialize(d.data instanceof ObjectField ? d.data[Copy]() : ''),
+ text: SerializationHelper.Serialize(d.text instanceof ObjectField ? d.text[Copy]() : ''),
+ })
+ )
+ );
if (pinProps.pinData.viewType) pinDoc.presPinViewType = targetDoc._viewType;
if (pinProps.pinData.filters) pinDoc.presPinDocFilters = ObjectField.MakeCopy(targetDoc.docFilters as ObjectField);
+ if (pinProps.pinData.pivot) pinDoc.presPinPivotField = targetDoc._pivotField;
if (pinProps.pinData.pannable) {
pinDoc.presPinViewX = NumCast(targetDoc._panX);
pinDoc.presPinViewY = NumCast(targetDoc._panY);
@@ -586,7 +638,7 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() {
const pinDocLayout = (BoolCast(activeItem.presPinLayout) || BoolCast(activeItem.presPinView)) && DocCast(targetDoc.context)?._currentFrame === undefined;
if (activeItem.presPinData || activeItem.presPinView || pinDocLayout) {
// targetDoc may or may not be displayed. so get the first available document (or alias) view that matches targetDoc and use it
- PresBox.restoreTargetDocView(DocumentManager.Instance.getFirstDocumentView(targetDoc), { pinDocLayout }, activeItem, NumCast(activeItem.presTransition, 500));
+ // PresBox.restoreTargetDocView(DocumentManager.Instance.getFirstDocumentView(targetDoc), { pinDocLayout }, activeItem, NumCast(activeItem.presTransition, 500), undefined, targetDoc);
}
};
const finishAndRestoreLayout = () => {
@@ -660,16 +712,43 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() {
_exitTrail: Opt<() => void>;
PlayTrail = (docs: Doc[]) => {
- const savedStates = docs.map(doc => (doc._viewType !== CollectionViewType.Freeform ? undefined : { c: doc, x: NumCast(doc.panX), y: NumCast(doc.panY), s: NumCast(doc.viewScale) }));
+ const savedStates = docs.map(doc => {
+ switch (doc.type) {
+ case DocumentType.COL:
+ if (doc._viewType === CollectionViewType.Freeform) return { type: CollectionViewType.Freeform, doc, x: NumCast(doc.panX), y: NumCast(doc.panY), s: NumCast(doc.viewScale) };
+ break;
+ case DocumentType.INK:
+ if (doc.data instanceof InkField) {
+ return { type: doc.type, doc, data: doc.data?.[Copy](), fillColor: doc.fillColor, color: doc.color, x: NumCast(doc.x), y: NumCast(doc.y) };
+ }
+ }
+ return undefined;
+ });
this.startPresentation(0);
this._exitTrail = () => {
savedStates
.filter(savedState => savedState)
.map(savedState => {
- const { x, y, s, c } = savedState!;
- c._panX = x;
- c._panY = y;
- c._viewScale = s;
+ switch (savedState?.type) {
+ case CollectionViewType.Freeform:
+ {
+ const { x, y, s, doc } = savedState!;
+ doc._panX = x;
+ doc._panY = y;
+ doc._viewScale = s;
+ }
+ break;
+ case DocumentType.INK:
+ {
+ const { data, fillColor, color, x, y, doc } = savedState!;
+ doc.x = x;
+ doc.y = y;
+ doc.data = data;
+ doc.fillColor = fillColor;
+ doc.color = color;
+ }
+ break;
+ }
});
LightboxView.SetLightboxDoc(undefined);
Doc.RemoveDocFromList(Doc.MyOverlayDocs, undefined, this.rootDoc);
@@ -1869,7 +1948,7 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() {
);
}
- scrollFocus = () => {
+ scrollFocus = (docView: DocumentView, doc: Doc, options: DocFocusOptions) => {
// this.gotoDocument(0);
// this.startOrPause(false);
return undefined;