From 513dcaa2d8c86f1cb5236ce89062cace6f418d1b Mon Sep 17 00:00:00 2001 From: bobzel Date: Wed, 10 Aug 2022 14:52:04 -0400 Subject: cleaned up pinning documents with an activeFrame index (and special case of isInkMask). removed text-color from pres boxes which was breaking opacity when docs had an appearFrame > 0. --- src/client/views/DocumentButtonBar.tsx | 18 +- src/client/views/collections/CollectionMenu.tsx | 25 ++- src/client/views/collections/TabDocView.tsx | 15 +- .../views/nodes/CollectionFreeFormDocumentView.tsx | 208 ++++++++++++--------- src/client/views/nodes/DocumentView.tsx | 4 +- src/client/views/nodes/trails/PresBox.tsx | 23 +-- 6 files changed, 163 insertions(+), 130 deletions(-) (limited to 'src') diff --git a/src/client/views/DocumentButtonBar.tsx b/src/client/views/DocumentButtonBar.tsx index 1f8550ad6..40fc8dae6 100644 --- a/src/client/views/DocumentButtonBar.tsx +++ b/src/client/views/DocumentButtonBar.tsx @@ -5,7 +5,7 @@ import { action, computed, observable, runInAction } from 'mobx'; import { observer } from 'mobx-react'; import { Doc } from '../../fields/Doc'; import { RichTextField } from '../../fields/RichTextField'; -import { Cast, NumCast } from '../../fields/Types'; +import { Cast, DocCast, NumCast } from '../../fields/Types'; import { emptyFunction, returnFalse, setupMoveUpEvents, simulateMouseClick } from '../../Utils'; import { GoogleAuthenticationManager } from '../apis/GoogleAuthenticationManager'; import { Pulls, Pushes } from '../apis/google_docs/GoogleApiClientUtils'; @@ -238,15 +238,13 @@ export class DocumentButtonBar extends React.Component<{ views: () => (DocumentV
- TabDocView.PinDoc( - this.props - .views() - .filter(v => v) - .map(dv => dv!.rootDoc), - { pinDocView: true } - ) - }> + onClick={e => { + const docs = this.props + .views() + .filter(v => v) + .map(dv => dv!.rootDoc); + TabDocView.PinDoc(docs, { pinDocView: true, activeFrame: Cast(docs.lastElement()?.activeFrame, 'number', null) }); + }}>
diff --git a/src/client/views/collections/CollectionMenu.tsx b/src/client/views/collections/CollectionMenu.tsx index cfbcec2d6..8432619de 100644 --- a/src/client/views/collections/CollectionMenu.tsx +++ b/src/client/views/collections/CollectionMenu.tsx @@ -769,6 +769,21 @@ export class CollectionFreeFormViewChrome extends React.Component { @@ -1569,13 +1584,5 @@ export class CollectionGridViewChrome extends React.Component { pinDoc.presEndTime = NumCast(doc.clipEnd, duration); } //save position - if (pinProps?.setPosition || pinDoc.isInkMask) { - pinDoc.setPosition = true; - pinDoc.y = doc.y; - pinDoc.x = doc.x; - pinDoc.presHideAfter = true; - pinDoc.presHideBefore = true; + if (pinProps?.activeFrame !== undefined) { + pinDoc.presActiveFrame = pinProps?.activeFrame; pinDoc.title = doc.title + ' (move)'; - pinDoc.presMovement = PresMovement.None; + pinDoc.presMovement = PresMovement.Pan; + if (pinDoc.isInkMask) { + pinDoc.presHideAfter = true; + pinDoc.presHideBefore = true; + pinDoc.presMovement = PresMovement.None; + } } if (curPres.expandBoolean) pinDoc.presExpandInlineButton = true; PresBox.Instance?._selectedArray.clear(); diff --git a/src/client/views/nodes/CollectionFreeFormDocumentView.tsx b/src/client/views/nodes/CollectionFreeFormDocumentView.tsx index 284584a3d..e154e8445 100644 --- a/src/client/views/nodes/CollectionFreeFormDocumentView.tsx +++ b/src/client/views/nodes/CollectionFreeFormDocumentView.tsx @@ -1,26 +1,26 @@ -import { action, computed, observable, trace } from "mobx"; -import { observer } from "mobx-react"; -import { Doc, Opt } from "../../../fields/Doc"; -import { List } from "../../../fields/List"; -import { listSpec } from "../../../fields/Schema"; -import { ComputedField } from "../../../fields/ScriptField"; -import { Cast, NumCast, StrCast } from "../../../fields/Types"; -import { TraceMobx } from "../../../fields/util"; -import { DashColor, numberRange, OmitKeys } from "../../../Utils"; -import { DocumentManager } from "../../util/DocumentManager"; -import { SelectionManager } from "../../util/SelectionManager"; -import { Transform } from "../../util/Transform"; -import { CollectionFreeFormView } from "../collections/collectionFreeForm/CollectionFreeFormView"; -import { DocComponent } from "../DocComponent"; -import { InkingStroke } from "../InkingStroke"; -import { StyleProp } from "../StyleProvider"; -import "./CollectionFreeFormDocumentView.scss"; -import { DocumentView, DocumentViewProps } from "./DocumentView"; -import React = require("react"); +import { action, computed, observable, trace } from 'mobx'; +import { observer } from 'mobx-react'; +import { Doc, Opt } from '../../../fields/Doc'; +import { List } from '../../../fields/List'; +import { listSpec } from '../../../fields/Schema'; +import { ComputedField } from '../../../fields/ScriptField'; +import { Cast, NumCast, StrCast } from '../../../fields/Types'; +import { TraceMobx } from '../../../fields/util'; +import { DashColor, numberRange, OmitKeys } from '../../../Utils'; +import { DocumentManager } from '../../util/DocumentManager'; +import { SelectionManager } from '../../util/SelectionManager'; +import { Transform } from '../../util/Transform'; +import { CollectionFreeFormView } from '../collections/collectionFreeForm/CollectionFreeFormView'; +import { DocComponent } from '../DocComponent'; +import { InkingStroke } from '../InkingStroke'; +import { StyleProp } from '../StyleProvider'; +import './CollectionFreeFormDocumentView.scss'; +import { DocumentView, DocumentViewProps } from './DocumentView'; +import React = require('react'); export interface CollectionFreeFormDocumentViewProps extends DocumentViewProps { - dataProvider?: (doc: Doc, replica: string) => { x: number, y: number, zIndex?: number, opacity?: number, highlight?: boolean, z: number, transition?: string } | undefined; - sizeProvider?: (doc: Doc, replica: string) => { width: number, height: number } | undefined; + dataProvider?: (doc: Doc, replica: string) => { x: number; y: number; zIndex?: number; opacity?: number; highlight?: boolean; z: number; transition?: string } | undefined; + sizeProvider?: (doc: Doc, replica: string) => { width: number; height: number } | undefined; renderCutoffProvider: (doc: Doc) => boolean; zIndex?: number; highlight?: boolean; @@ -32,29 +32,51 @@ export interface CollectionFreeFormDocumentViewProps extends DocumentViewProps { @observer export class CollectionFreeFormDocumentView extends DocComponent() { - public static animFields = ["_height", "_width", "x", "y", "_scrollTop", "opacity"]; // fields that are configured to be animatable using animation frames + public static animFields = ['_height', '_width', 'x', 'y', '_scrollTop', 'opacity']; // fields that are configured to be animatable using animation frames @observable _animPos: number[] | undefined = undefined; @observable _contentView: DocumentView | undefined | null; - get displayName() { return "CollectionFreeFormDocumentView(" + this.rootDoc.title + ")"; } // this makes mobx trace() statements more descriptive - get maskCentering() { return this.props.Document.isInkMask ? InkingStroke.MaskDim / 2 : 0; } - get transform() { return `translate(${this.X - this.maskCentering}px, ${this.Y - this.maskCentering}px) rotate(${NumCast(this.Document.jitterRotation, this.props.jitterRotation)}deg)`; } - get X() { return this.dataProvider ? this.dataProvider.x : NumCast(this.Document.x); } - get Y() { return this.dataProvider ? this.dataProvider.y : NumCast(this.Document.y); } - get ZInd() { return this.dataProvider ? this.dataProvider.zIndex : NumCast(this.Document.zIndex); } - get Opacity() { return this.dataProvider ? this.dataProvider.opacity : undefined; } - get Highlight() { return this.dataProvider?.highlight; } - @computed get ShowTitle() { return this.props.styleProvider?.(this.rootDoc, this.props, StyleProp.ShowTitle) as (Opt); } - @computed get dataProvider() { return this.props.dataProvider?.(this.props.Document, this.props.replica); } - @computed get sizeProvider() { return this.props.sizeProvider?.(this.props.Document, this.props.replica); } + get displayName() { + return 'CollectionFreeFormDocumentView(' + this.rootDoc.title + ')'; + } // this makes mobx trace() statements more descriptive + get maskCentering() { + return this.props.Document.isInkMask ? InkingStroke.MaskDim / 2 : 0; + } + get transform() { + return `translate(${this.X - this.maskCentering}px, ${this.Y - this.maskCentering}px) rotate(${NumCast(this.Document.jitterRotation, this.props.jitterRotation)}deg)`; + } + get X() { + return this.dataProvider ? this.dataProvider.x : NumCast(this.Document.x); + } + get Y() { + return this.dataProvider ? this.dataProvider.y : NumCast(this.Document.y); + } + get ZInd() { + return this.dataProvider ? this.dataProvider.zIndex : NumCast(this.Document.zIndex); + } + get Opacity() { + return this.dataProvider ? this.dataProvider.opacity : undefined; + } + get Highlight() { + return this.dataProvider?.highlight; + } + @computed get ShowTitle() { + return this.props.styleProvider?.(this.rootDoc, this.props, StyleProp.ShowTitle) as Opt; + } + @computed get dataProvider() { + return this.props.dataProvider?.(this.props.Document, this.props.replica); + } + @computed get sizeProvider() { + return this.props.sizeProvider?.(this.props.Document, this.props.replica); + } styleProvider = (doc: Doc | undefined, props: Opt, property: string) => { if (property === StyleProp.Opacity && doc === this.layoutDoc) return this.Opacity; // only change the opacity for this specific document, not its children return this.props.styleProvider?.(doc, props, property); - } + }; public static getValues(doc: Doc, time: number) { return CollectionFreeFormDocumentView.animFields.reduce((p, val) => { - p[val] = Cast(`${val}-indexed`, listSpec("number"), [NumCast(doc[val])]).reduce((p, v, i) => (i <= Math.round(time) && v !== undefined) || p === undefined ? v : p, undefined as any as number); + p[val] = Cast(`${val}-indexed`, listSpec('number'), [NumCast(doc[val])]).reduce((p, v, i) => ((i <= Math.round(time) && v !== undefined) || p === undefined ? v : p), undefined as any as number); return p; }, {} as { [val: string]: Opt }); } @@ -62,35 +84,43 @@ export class CollectionFreeFormDocumentView extends DocComponent }) { const timecode = Math.round(time); Object.keys(vals).forEach(val => { - const findexed = Cast(d[`${val}-indexed`], listSpec("number"), []).slice(); + const findexed = Cast(d[`${val}-indexed`], listSpec('number'), []).slice(); findexed[timecode] = vals[val] as any as number; d[`${val}-indexed`] = new List(findexed); }); - d.appearFrame && (d["text-color"] = - d.appearFrame === timecode + 1 ? "red" : - d.appearFrame < timecode + 1 ? "grey" : "black"); } public static updateKeyframe(docs: Doc[], time: number, targetDoc?: Doc) { const timecode = Math.round(time); - docs.forEach(action(doc => { - doc._viewTransition = doc.dataTransition = "all 1s"; - doc["text-color"] = - !doc.appearFrame || !targetDoc ? "black" : - doc.appearFrame === timecode + 1 ? StrCast(targetDoc["pres-text-color"]) : - doc.appearFrame < timecode + 1 ? StrCast(targetDoc["pres-text-viewed-color"]) : - "black"; - CollectionFreeFormDocumentView.animFields.forEach(val => { - const findexed = Cast(doc[`${val}-indexed`], listSpec("number"), null); - findexed?.length <= timecode + 1 && findexed.push(undefined as any as number); - }); - })); - setTimeout(() => docs.forEach(doc => { doc._viewTransition = undefined; doc.dataTransition = "inherit"; }), 1010); + docs.forEach( + action(doc => { + doc._viewTransition = doc.dataTransition = 'all 1s'; + CollectionFreeFormDocumentView.animFields.forEach(val => { + const findexed = Cast(doc[`${val}-indexed`], listSpec('number'), null); + findexed?.length <= timecode + 1 && findexed.push(undefined as any as number); + }); + }) + ); + setTimeout( + () => + docs.forEach(doc => { + doc._viewTransition = undefined; + doc.dataTransition = 'inherit'; + }), + 1010 + ); } public static gotoKeyframe(docs: Doc[]) { - docs.forEach(doc => doc._viewTransition = doc.dataTransition = "all 1s"); - setTimeout(() => docs.forEach(doc => { doc._viewTransition = undefined; doc.dataTransition = "inherit"; }), 1010); + docs.forEach(doc => (doc._viewTransition = doc.dataTransition = 'all 1s')); + setTimeout( + () => + docs.forEach(doc => { + doc._viewTransition = undefined; + doc.dataTransition = 'inherit'; + }), + 1010 + ); } public static setupZoom(doc: Doc, targDoc: Doc) { @@ -102,21 +132,22 @@ export class CollectionFreeFormDocumentView extends DocComponent { if (doc.appearFrame === undefined) doc.appearFrame = currTimecode; - if (!doc["opacity-indexed"]) { // opacity is unlike other fields because it's value should not be undefined before it appears to enable it to fade-in - doc["opacity-indexed"] = new List(numberRange(currTimecode + 1).map(t => !doc.z && makeAppear && t < NumCast(doc.appearFrame) ? 0 : 1)); + if (!doc['opacity-indexed']) { + // opacity is unlike other fields because it's value should not be undefined before it appears to enable it to fade-in + doc['opacity-indexed'] = new List(numberRange(currTimecode + 1).map(t => (!doc.z && makeAppear && t < NumCast(doc.appearFrame) ? 0 : 1))); } - CollectionFreeFormDocumentView.animFields.forEach(val => doc[val] = ComputedField.MakeInterpolated(val, "activeFrame", doc, currTimecode)); - doc.activeFrame = ComputedField.MakeFunction("self.context?._currentFrame||0"); - doc.dataTransition = "inherit"; + CollectionFreeFormDocumentView.animFields.forEach(val => (doc[val] = ComputedField.MakeInterpolated(val, 'activeFrame', doc, currTimecode))); + doc.activeFrame = ComputedField.MakeFunction('self.context?._currentFrame||0'); + doc.dataTransition = 'inherit'; }); } @@ -131,7 +162,7 @@ export class CollectionFreeFormDocumentView extends DocComponent SelectionManager.SelectView(DocumentManager.Instance.getDocumentView(topDoc, container)!, false), 0); } - } + }; nudge = (x: number, y: number) => { this.props.Document.x = NumCast(this.props.Document.x) + x; this.props.Document.y = NumCast(this.props.Document.y) + y; - } - panelWidth = () => (this.sizeProvider?.width || this.props.PanelWidth?.()); - panelHeight = () => (this.sizeProvider?.height || this.props.PanelHeight?.()); + }; + panelWidth = () => this.sizeProvider?.width || this.props.PanelWidth?.(); + panelHeight = () => this.sizeProvider?.height || this.props.PanelHeight?.(); screenToLocalTransform = (): Transform => this.props.ScreenToLocalTransform().translate(-this.X, -this.Y); focusDoc = (doc: Doc) => this.props.focus(doc); returnThis = () => this; @@ -163,24 +194,27 @@ export class CollectionFreeFormDocumentView extends DocComponent - {this.props.renderCutoffProvider(this.props.Document) ? -
- : - this._contentView = r)} /> - } -
; + const mixBlendMode = (StrCast(this.layoutDoc.mixBlendMode) as any) || (typeof background === 'string' && background && !background.startsWith('linear') && DashColor(background).alpha() !== 1 ? 'multiply' : undefined); + return ( +
+ {this.props.renderCutoffProvider(this.props.Document) ? ( +
+ ) : ( + (this._contentView = r))} /> + )} +
+ ); } } diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx index f87581875..f9ef85595 100644 --- a/src/client/views/nodes/DocumentView.tsx +++ b/src/client/views/nodes/DocumentView.tsx @@ -1640,8 +1640,8 @@ export class DocumentView extends React.Component { render() { TraceMobx(); - const xshift = () => (this.props.Document.isInkMask ? InkingStroke.MaskDim : Math.abs(this.Xshift) <= 0.001 ? this.props.PanelWidth() : undefined); - const yshift = () => (this.props.Document.isInkMask ? InkingStroke.MaskDim : Math.abs(this.Yshift) <= 0.001 ? this.props.PanelHeight() : undefined); + const xshift = () => (this.props.Document.isInkMask && !this.props.LayoutTemplateString && !this.props.LayoutTemplate?.() ? InkingStroke.MaskDim : Math.abs(this.Xshift) <= 0.001 ? this.props.PanelWidth() : undefined); + const yshift = () => (this.props.Document.isInkMask && !this.props.LayoutTemplateString && !this.props.LayoutTemplate?.() ? InkingStroke.MaskDim : Math.abs(this.Yshift) <= 0.001 ? this.props.PanelHeight() : undefined); const isPresTreeElement: boolean = this.props.treeViewDoc?.type === DocumentType.PRES; const isButton: boolean = this.props.Document.type === DocumentType.FONTICON || this.props.Document._viewType === CollectionViewType.Linear; return ( diff --git a/src/client/views/nodes/trails/PresBox.tsx b/src/client/views/nodes/trails/PresBox.tsx index 6e5eb3300..3bbdce1e4 100644 --- a/src/client/views/nodes/trails/PresBox.tsx +++ b/src/client/views/nodes/trails/PresBox.tsx @@ -29,10 +29,11 @@ import { CollectionFreeFormDocumentView } from '../CollectionFreeFormDocumentVie import { FieldView, FieldViewProps } from '../FieldView'; import './PresBox.scss'; import { PresEffect, PresMovement, PresStatus } from './PresEnums'; +import { CollectionFreeFormViewChrome } from '../../collections/CollectionMenu'; export interface PinProps { audioRange?: boolean; - setPosition?: boolean; + activeFrame?: number; hidePresBox?: boolean; pinWithView?: PinViewProps; pinDocView?: boolean; // whether the current view specs of the document should be saved the pinned document @@ -509,7 +510,7 @@ export class PresBox extends ViewBoxBaseComponent() { this.childDocs.forEach((doc, index) => { const curDoc = Cast(doc, Doc, null); const tagDoc = Cast(curDoc.presentationTargetDoc, Doc, null); - if (tagDoc) tagDoc.opacity = 1; + //if (tagDoc) tagDoc.opacity = 1; const itemIndexes: number[] = this.getAllIndexes(this.tagDocs, tagDoc); const curInd: number = itemIndexes.indexOf(index); if (tagDoc === this.layoutDoc.presCollection) { @@ -519,7 +520,7 @@ export class PresBox extends ViewBoxBaseComponent() { } else if (curDoc.presHideBefore) { if (index > this.itemIndex) { tagDoc.opacity = 0; - } else if (!curDoc.presHideAfter) { + } else if (index === this.itemIndex || !curDoc.presHideAfter) { tagDoc.opacity = 1; } } @@ -527,7 +528,7 @@ export class PresBox extends ViewBoxBaseComponent() { } else if (curDoc.presHideAfter) { if (index < this.itemIndex) { tagDoc.opacity = 0; - } else if (!curDoc.presHideBefore) { + } else if (index === this.itemIndex || !curDoc.presHideBefore) { tagDoc.opacity = 1; } } @@ -821,17 +822,9 @@ export class PresBox extends ViewBoxBaseComponent() { if (doc.presPinView || doc.presentationTargetDoc === this.layoutDoc.presCollection) setTimeout(() => this.updateCurrentPresentation(context), 0); else this.updateCurrentPresentation(context); - if (this.activeItem.setPosition && this.activeItem.y !== undefined && this.activeItem.x !== undefined && this.targetDoc.x !== undefined && this.targetDoc.y !== undefined) { - const timer = (ms: number) => new Promise(res => (this._presTimer = setTimeout(res, ms))); - const time = 10; - const ydiff = NumCast(this.activeItem.y) - NumCast(this.targetDoc.y); - const xdiff = NumCast(this.activeItem.x) - NumCast(this.targetDoc.x); - - for (let i = 0; i < time; i++) { - this.targetDoc.x = NumCast(this.targetDoc.x) + xdiff / time; - this.targetDoc.y = NumCast(this.targetDoc.y) + ydiff / time; - await timer(0.1); - } + if (this.activeItem.presActiveFrame !== undefined) { + const context = DocCast(DocCast(this.activeItem.presentationTargetDoc).context); + context && CollectionFreeFormViewChrome.gotoKeyFrame(context, NumCast(this.activeItem.presActiveFrame)); } }; -- cgit v1.2.3-70-g09d2