diff options
8 files changed, 76 insertions, 47 deletions
diff --git a/src/client/views/DocumentButtonBar.tsx b/src/client/views/DocumentButtonBar.tsx index 3b22cf51c..fa0b9a238 100644 --- a/src/client/views/DocumentButtonBar.tsx +++ b/src/client/views/DocumentButtonBar.tsx @@ -201,13 +201,15 @@ export class DocumentButtonBar extends React.Component<{ views: () => (DocumentV if (targetDoc) { TabDocView.PinDoc(targetDoc, false); const activeDoc = PresBox.Instance.childDocs[PresBox.Instance.childDocs.length - 1]; - if (targetDoc.type === DocumentType.PDF || targetDoc.type === DocumentType.RTF || targetDoc.type === DocumentType.WEB || targetDoc._viewType === CollectionViewType.Stacking) { + const scrollable: boolean = (targetDoc.type === DocumentType.PDF || targetDoc.type === DocumentType.RTF || targetDoc.type === DocumentType.WEB || targetDoc._viewType === CollectionViewType.Stacking); + const pannable: boolean = ((targetDoc.type === DocumentType.COL && targetDoc._viewType === CollectionViewType.Freeform) || targetDoc.type === DocumentType.IMG); + if (scrollable) { const scroll = targetDoc._scrollTop; activeDoc.presPinView = true; activeDoc.presPinViewScroll = scroll; } else if (targetDoc.type === DocumentType.VID) { activeDoc.presPinTimecode = targetDoc._currentTimecode; - } else if ((targetDoc.type === DocumentType.COL && targetDoc._viewType === CollectionViewType.Freeform) || targetDoc.type === DocumentType.IMG) { + } else if (pannable) { const x = targetDoc._panX; const y = targetDoc._panY; const scale = targetDoc._viewScale; diff --git a/src/client/views/PropertiesView.tsx b/src/client/views/PropertiesView.tsx index 42f61f99a..fad2f5284 100644 --- a/src/client/views/PropertiesView.tsx +++ b/src/client/views/PropertiesView.tsx @@ -1029,7 +1029,7 @@ export class PropertiesView extends React.Component<PropertiesViewProps> { {PresBox.Instance.progressivizeDropdown} </div> : null} </div>} */} - {!selectedItem || (!scrollable && !pannable) ? (null) : <div className="propertiesView-presTrails"> + {/* {!selectedItem || (!scrollable && !pannable) ? (null) : <div className="propertiesView-presTrails"> <div className="propertiesView-presTrails-title" onPointerDown={action(() => { this.openSlideOptions = !this.openSlideOptions; })} style={{ backgroundColor: this.openSlideOptions ? "black" : "" }}> @@ -1041,7 +1041,7 @@ export class PropertiesView extends React.Component<PropertiesViewProps> { {this.openSlideOptions ? <div className="propertiesView-presTrails-content"> {PresBox.Instance.optionsDropdown} </div> : null} - </div>} + </div>} */} {/* <div className="propertiesView-presTrails"> <div className="propertiesView-presTrails-title" onPointerDown={action(() => { this.openAddSlide = !this.openAddSlide; })} diff --git a/src/client/views/collections/CollectionMenu.tsx b/src/client/views/collections/CollectionMenu.tsx index b44b85183..1dbafbd61 100644 --- a/src/client/views/collections/CollectionMenu.tsx +++ b/src/client/views/collections/CollectionMenu.tsx @@ -432,7 +432,7 @@ export class CollectionViewBaseChrome extends React.Component<CollectionMenuProp const presPinWithViewIcon = <img src={`/assets/pinWithView.png`} style={{ margin: "auto", width: 19 }} />; const targetDoc = this.selectedDoc; {/* return (!targetDoc || (targetDoc._viewType !== CollectionViewType.Freeform && targetDoc.type !== DocumentType.IMG)) ? (null) : <Tooltip title={<><div className="dash-tooltip">{"Pin to presentation trail with current view"}</div></>} placement="top"> */ } - return (targetDoc && targetDoc.type !== DocumentType.PRES && (targetDoc._viewType === CollectionViewType.Freeform || targetDoc._viewType === CollectionViewType.Stacking || targetDoc.type === DocumentType.VID || targetDoc.type === DocumentType.IMG || targetDoc.type === DocumentType.PDF || targetDoc.type === DocumentType.WEB || targetDoc.type === DocumentType.VID || targetDoc.type === DocumentType.RTF || targetDoc.type === DocumentType.COMPARISON)) ? <Tooltip title={<><div className="dash-tooltip">{"Pin to presentation trail with current view"}</div></>} placement="top"> + return (targetDoc && targetDoc.type !== DocumentType.PRES && (targetDoc._viewType === CollectionViewType.Freeform || targetDoc._viewType === CollectionViewType.Stacking || targetDoc.type === DocumentType.VID || targetDoc.type === DocumentType.IMG || targetDoc.type === DocumentType.PDF || targetDoc.type === DocumentType.WEB || targetDoc.type === DocumentType.VID || targetDoc.type === DocumentType.RTF || targetDoc.type === DocumentType.COMPARISON)) ? <Tooltip title={<><div className="dash-tooltip">{"Pin with current view"}</div></>} placement="top"> <button className="antimodeMenu-button" style={{ borderRight: "1px solid gray", borderLeft: "1px solid gray", justifyContent: 'center' }} onClick={() => this.pinWithView(targetDoc)}> {presPinWithViewIcon} diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.scss b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.scss index 75cbc20ca..e92100c50 100644 --- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.scss +++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.scss @@ -57,7 +57,7 @@ min-height: 15px; text-align: center; background-color: #69a6db; - border-radius: 5px; + border-radius: 10%; box-shadow: 0px 4px 4px rgba(0, 0, 0, 0.25); font-family: Roboto; font-weight: 500; @@ -65,6 +65,13 @@ } } +.pathOrder-presPinView { + position: absolute; + z-index: 190000; + border-style: dashed; + border-color: #69a5db; +} + .progressivizeButton { position: absolute; display: grid; diff --git a/src/client/views/collections/collectionFreeForm/MarqueeOptionsMenu.tsx b/src/client/views/collections/collectionFreeForm/MarqueeOptionsMenu.tsx index d8e44e781..cedeb1112 100644 --- a/src/client/views/collections/collectionFreeForm/MarqueeOptionsMenu.tsx +++ b/src/client/views/collections/collectionFreeForm/MarqueeOptionsMenu.tsx @@ -54,7 +54,7 @@ export class MarqueeOptionsMenu extends AntimodeMenu<AntimodeMenuProps> { <FontAwesomeIcon icon="font" size="lg" /> </button> </Tooltip>, - <Tooltip key="pinWithView" title={<><div className="dash-tooltip">Pin the selected region to presentation</div></>} placement="bottom"> + <Tooltip key="pinWithView" title={<><div className="dash-tooltip">Pin with selected region</div></>} placement="bottom"> <button className="antimodeMenu-button" onPointerDown={this.pinWithView}> diff --git a/src/client/views/nodes/PresBox.scss b/src/client/views/nodes/PresBox.scss index 07cf63532..a89bc73c6 100644 --- a/src/client/views/nodes/PresBox.scss +++ b/src/client/views/nodes/PresBox.scss @@ -1000,6 +1000,7 @@ $light-background: #ececec; transition: all 0.2s; .presPanel-button-text { + cursor: pointer; display: flex; height: 20; width: max-content; diff --git a/src/client/views/nodes/PresBox.tsx b/src/client/views/nodes/PresBox.tsx index dd7ba3e26..518d365ed 100644 --- a/src/client/views/nodes/PresBox.tsx +++ b/src/client/views/nodes/PresBox.tsx @@ -28,6 +28,7 @@ import { AudioBox } from "./AudioBox"; import { CollectionFreeFormDocumentView } from "./CollectionFreeFormDocumentView"; import { FieldView, FieldViewProps } from './FieldView'; import "./PresBox.scss"; +import Color = require("color"); export enum PresMovement { Zoom = "zoom", @@ -193,16 +194,15 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps, PresBoxSchema> // No more frames in current doc and next slide is defined, therefore move to next slide nextSlide = (targetDoc: Doc, activeNext: Doc) => { const nextSelected = this.itemIndex + 1; - if (targetDoc.type === DocumentType.AUDIO) { if (AudioBox.Instance._ele) AudioBox.Instance.pause(); } - // if (targetDoc.type === DocumentType.VID) { if (AudioBox.Instance._ele) VideoBox.Instance.Pause(); } - const targetNext = Cast(activeNext.presentationTargetDoc, Doc, null); - // If next slide is audio / video 'Play automatically' then the next slide should be played - if (activeNext && (targetNext.type === DocumentType.AUDIO || targetNext.type === DocumentType.VID) && activeNext.playAuto) { - console.log('play next automatically'); - if (targetNext.type === DocumentType.AUDIO) AudioBox.Instance.playFrom(NumCast(activeNext.presStartTime)); - // if (targetNext.type === DocumentType.VID) { VideoBox.Instance.Play() }; - } else if (targetNext.type === DocumentType.AUDIO || targetNext.type === DocumentType.VID) { activeNext.playNow = true; console.log('play next after it is navigated to'); } this.gotoDocument(nextSelected); + + // const targetNext = Cast(activeNext.presentationTargetDoc, Doc, null); + // If next slide is audio / video 'Play automatically' then the next slide should be played + // if (activeNext && (targetNext.type === DocumentType.AUDIO || targetNext.type === DocumentType.VID) && activeNext.playAuto) { + // console.log('play next automatically'); + // if (targetNext.type === DocumentType.AUDIO) AudioBox.Instance.playFrom(NumCast(activeNext.presStartTime)); + // // if (targetNext.type === DocumentType.VID) { VideoBox.Instance.Play() }; + // } else if (targetNext.type === DocumentType.AUDIO || targetNext.type === DocumentType.VID) { activeNext.playNow = true; console.log('play next after it is navigated to'); } } // Called when the user activates 'next' - to move to the next part of the pres. trail @@ -215,13 +215,9 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps, PresBoxSchema> const curFrame = NumCast(targetDoc?._currentFrame); let internalFrames: boolean = false; if (activeItem.presProgressivize || activeItem.zoomProgressivize || targetDoc.scrollProgressivize) internalFrames = true; - if (internalFrames && lastFrame !== undefined && curFrame < lastFrame) { // Case 1: There are still other frames and should go through all frames before going to next slide this.nextInternalFrame(targetDoc, activeItem); - } else if ((targetDoc.type === DocumentType.AUDIO || targetDoc.type === DocumentType.VID) && !activeItem.playAuto && activeItem.playNow && this.layoutDoc.presStatus !== PresStatus.Autoplay) { - // Case 2: 'Play on next' for audio or video therefore first navigate to the audio/video before it should be played - this.nextAudioVideo(targetDoc, activeItem); } else if (this.childDocs[this.itemIndex + 1] !== undefined) { // Case 3: No more frames in current doc and next slide is defined, therefore move to next slide this.nextSlide(targetDoc, activeNext); @@ -229,6 +225,10 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps, PresBoxSchema> // Case 4: Last slide and presLoop is toggled ON this.gotoDocument(0); } + // else if ((targetDoc.type === DocumentType.AUDIO || targetDoc.type === DocumentType.VID) && !activeItem.playAuto && activeItem.playNow && this.layoutDoc.presStatus !== PresStatus.Autoplay) { + // // Case 2: 'Play on next' for audio or video therefore first navigate to the audio/video before it should be played + // this.nextAudioVideo(targetDoc, activeItem); + // } } // Called when the user activates 'back' - to move to the previous part of the pres. trail @@ -240,14 +240,18 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps, PresBoxSchema> const prevTargetDoc = Cast(prevItem.presentationTargetDoc, Doc, null); const lastFrame = Cast(targetDoc.lastFrame, "number", null); const curFrame = NumCast(targetDoc._currentFrame); + let prevSelected = this.itemIndex; if (lastFrame !== undefined && curFrame >= 1) { // Case 1: There are still other frames and should go through all frames before going to previous slide this.prevKeyframe(targetDoc, activeItem); - } else if (activeItem) { - let prevSelected = this.itemIndex; + } else if (activeItem && this.childDocs[this.itemIndex - 1] !== undefined) { + // Case 2: There are no other frames so it should go to the previous slide prevSelected = Math.max(0, prevSelected - 1); this.gotoDocument(prevSelected); if (NumCast(prevTargetDoc.lastFrame) > 0) prevTargetDoc._currentFrame = NumCast(prevTargetDoc.lastFrame); + } else if (this.childDocs[this.itemIndex - 1] === undefined && this.layoutDoc.presLoop) { + // Case 3: Pres loop is on so it should go to the last slide + this.gotoDocument(this.childDocs.length - 1); } } @@ -750,8 +754,7 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps, PresBoxSchema> break; case "Down": case "ArrowDown": case "Right": case "ArrowRight": - if (this.itemIndex >= this.childDocs.length - 1) return; - if (e.shiftKey) { // TODO: update to work properly + if (e.shiftKey && this.itemIndex < this.childDocs.length - 1) { // TODO: update to work properly this.rootDoc._itemIndex = NumCast(this.rootDoc._itemIndex) + 1; this._selectedArray.set(this.childDocs[this.rootDoc._itemIndex], undefined); } else { @@ -762,8 +765,7 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps, PresBoxSchema> break; case "Up": case "ArrowUp": case "Left": case "ArrowLeft": - if (this.itemIndex === 0) return; - if (e.shiftKey) { // TODO: update to work properly + if (e.shiftKey && this.itemIndex !== 0) { // TODO: update to work properly this.rootDoc._itemIndex = NumCast(this.rootDoc._itemIndex) - 1; this._selectedArray.set(this.childDocs[this.rootDoc._itemIndex], undefined); } else { @@ -815,6 +817,8 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps, PresBoxSchema> @computed get order() { const order: JSX.Element[] = []; const docs: Doc[] = []; + const presCollection = Cast(this.rootDoc.presCollection, Doc, null); + const dv = DocumentManager.Instance.getDocumentView(presCollection); this.childDocs.filter(doc => Cast(doc.presentationTargetDoc, Doc, null)).forEach((doc, index) => { const tagDoc = Cast(doc.presentationTargetDoc, Doc, null); const srcContext = Cast(tagDoc.context, Doc, null); @@ -823,8 +827,8 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps, PresBoxSchema> const edge = Math.max(width, height); const fontSize = edge * 0.8; const gap = 2; - // Case A: Document is contained within the collection - if (this.rootDoc.presCollection === srcContext) { + if (presCollection === srcContext) { + // Case A: Document is contained within the collection if (docs.includes(tagDoc)) { const prevOccurances: number = this.getAllIndexes(docs, tagDoc).length; docs.push(tagDoc); @@ -845,20 +849,29 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps, PresBoxSchema> <div className="pathOrder-frame">{index + 1}</div> </div>); } + } else if (doc.presPinView && presCollection === tagDoc && dv) { // Case B: Document is presPinView and is presCollection - } else if (doc.pinWithView && this.layoutDoc.presCollection === tagDoc) { + const scale: number = 1 / NumCast(doc.presPinViewScale); + const height: number = dv.props.PanelHeight() * scale; + const width: number = dv.props.PanelWidth() * scale; + const indWidth = width / 10; + const indHeight = Math.max(height / 10, 15); + const indEdge = Math.max(indWidth, indHeight); + const indFontSize = indEdge * 0.8; + const xLoc: number = NumCast(doc.presPinViewX) - (width / 2); + const yLoc: number = NumCast(doc.presPinViewY) - (height / 2); docs.push(tagDoc); order.push( - <div className="pathOrder" key={tagDoc.id + 'pres' + index} style={{ top: 0, left: 0 }}> - <div className="pathOrder-frame">{index + 1}</div> - </div>); - // Case C: Document is not contained within presCollection - } else { - docs.push(tagDoc); - order.push( - <div className="pathOrder" key={tagDoc.id + 'pres' + index} style={{ position: 'absolute', top: 0, left: 0 }}> - <div className="pathOrder-frame">{index + 1}</div> - </div>); + <> + <div className="pathOrder" + key={tagDoc.id + 'pres' + index} + style={{ top: yLoc - (indEdge / 2), left: xLoc - (indEdge / 2), width: indEdge, height: indEdge, fontSize: indFontSize }} + onClick={() => this.selectElement(doc)} + > + <div className="pathOrder-frame">{index + 1}</div> + </div> + <div className="pathOrder-presPinView" style={{ top: yLoc, left: xLoc, width: width, height: height, borderWidth: indEdge / 10 }}></div> + </>); } }); return order; @@ -874,17 +887,20 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps, PresBoxSchema> */ @computed get paths() { let pathPoints = ""; + const presCollection = Cast(this.rootDoc.presCollection, Doc, null); this.childDocs.forEach((doc, index) => { const tagDoc = Cast(doc.presentationTargetDoc, Doc, null); const srcContext = Cast(tagDoc?.context, Doc, null); - if (tagDoc && this.rootDoc.presCollection === srcContext) { + if (tagDoc && presCollection === srcContext) { const n1x = NumCast(tagDoc.x) + (NumCast(tagDoc._width) / 2); const n1y = NumCast(tagDoc.y) + (NumCast(tagDoc._height) / 2); if (index = 0) pathPoints = n1x + "," + n1y; else pathPoints = pathPoints + " " + n1x + "," + n1y; - } else { - if (index = 0) pathPoints = 0 + "," + 0; - else pathPoints = pathPoints + " " + 0 + "," + 0; + } else if (doc.presPinView && presCollection === tagDoc) { + const n1x = NumCast(doc.presPinViewX); + const n1y = NumCast(doc.presPinViewY); + if (index = 0) pathPoints = n1x + "," + n1y; + else pathPoints = pathPoints + " " + n1x + "," + n1y; } }); return (<polyline @@ -2021,7 +2037,10 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps, PresBoxSchema> <Tooltip title={<><div className="dash-tooltip">{this.layoutDoc.presStatus === PresStatus.Autoplay ? "Pause" : "Autoplay"}</div></>}><div className="presPanel-button" onClick={this.startOrPause}><FontAwesomeIcon icon={this.layoutDoc.presStatus === PresStatus.Autoplay ? "pause" : "play"} /></div></Tooltip> <div className="presPanel-button" onClick={() => { this.next(); if (this._presTimer) { clearTimeout(this._presTimer); this.layoutDoc.presStatus = PresStatus.Manual; } }}><FontAwesomeIcon icon={"arrow-right"} /></div> <div className="presPanel-divider"></div> - <div className="presPanel-button-text" style={{ display: this.props.PanelWidth() > 250 ? "inline-flex" : "none" }}> + <div + className="presPanel-button-text" + onClick={() => this.gotoDocument(0)} + style={{ display: this.props.PanelWidth() > 250 ? "inline-flex" : "none" }}> Slide {this.itemIndex + 1} / {this.childDocs.length} {this.playButtonFrames} </div> @@ -2055,7 +2074,7 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps, PresBoxSchema> <Tooltip title={<><div className="dash-tooltip">{this.layoutDoc.presStatus === PresStatus.Autoplay ? "Pause" : "Autoplay"}</div></>}><div className="presPanel-button" onClick={this.startOrPause}><FontAwesomeIcon icon={this.layoutDoc.presStatus === "auto" ? "pause" : "play"} /></div></Tooltip> <div className="presPanel-button" onClick={() => { this.next(); if (this._presTimer) { clearTimeout(this._presTimer); this.layoutDoc.presStatus = PresStatus.Manual; } }}><FontAwesomeIcon icon={"arrow-right"} /></div> <div className="presPanel-divider"></div> - <div className="presPanel-button-text"> + <div className="presPanel-button-text" onClick={() => this.gotoDocument(0)}> Slide {this.itemIndex + 1} / {this.childDocs.length} {this.playButtonFrames} </div> diff --git a/src/client/views/presentationview/PresElementBox.tsx b/src/client/views/presentationview/PresElementBox.tsx index 7a28f8bff..b2acad86e 100644 --- a/src/client/views/presentationview/PresElementBox.tsx +++ b/src/client/views/presentationview/PresElementBox.tsx @@ -120,14 +120,14 @@ export class PresElementBox extends ViewBoxBaseComponent<FieldViewProps, PresDoc if (this.rootDoc.type === DocumentType.AUDIO) { durationInS = NumCast(this.rootDoc.presEndTime) - NumCast(this.rootDoc.presStartTime); durationInS = Math.round(durationInS * 10) / 10; } else if (this.rootDoc.presDuration) durationInS = NumCast(this.rootDoc.presDuration) / 1000; else durationInS = 2; - return this.rootDoc.presMovement === PresMovement.Jump ? (null) : "D: " + durationInS + "s"; + return "D: " + durationInS + "s"; } @computed get transition() { let transitionInS: number; if (this.rootDoc.presTransition) transitionInS = NumCast(this.rootDoc.presTransition) / 1000; else transitionInS = 0.5; - return "M: " + transitionInS + "s"; + return this.rootDoc.presMovement === PresMovement.Jump || this.rootDoc.presMovement === PresMovement.None ? (null) : "M: " + transitionInS + "s"; } private _itemRef: React.RefObject<HTMLDivElement> = React.createRef(); |