diff options
Diffstat (limited to 'src/client/views/nodes/trails/PresElementBox.tsx')
-rw-r--r-- | src/client/views/nodes/trails/PresElementBox.tsx | 236 |
1 files changed, 148 insertions, 88 deletions
diff --git a/src/client/views/nodes/trails/PresElementBox.tsx b/src/client/views/nodes/trails/PresElementBox.tsx index e6d08cd53..5d14a0e9a 100644 --- a/src/client/views/nodes/trails/PresElementBox.tsx +++ b/src/client/views/nodes/trails/PresElementBox.tsx @@ -4,7 +4,9 @@ import { action, computed, IReactionDisposer, observable, reaction } from 'mobx' import { observer } from 'mobx-react'; import { Doc, DocListCast, HeightSym, Opt, WidthSym } from '../../../../fields/Doc'; import { Copy, Id } from '../../../../fields/FieldSymbols'; +import { InkField } from '../../../../fields/InkField'; import { List } from '../../../../fields/List'; +import { RichTextField } from '../../../../fields/RichTextField'; import { Cast, DocCast, NumCast, StrCast } from '../../../../fields/Types'; import { emptyFunction, returnEmptyDoclist, returnFalse, returnTrue, setupMoveUpEvents } from '../../../../Utils'; import { Docs, DocUtils } from '../../../documents/Documents'; @@ -14,6 +16,7 @@ import { DragManager } from '../../../util/DragManager'; import { SettingsManager } from '../../../util/SettingsManager'; import { Transform } from '../../../util/Transform'; import { undoBatch } from '../../../util/UndoManager'; +import { MarqueeView } from '../../collections/collectionFreeForm'; import { ViewBoxBaseComponent } from '../../DocComponent'; import { EditableView } from '../../EditableView'; import { Colors } from '../../global/globalEnums'; @@ -24,8 +27,6 @@ import { PresBox } from './PresBox'; import './PresElementBox.scss'; import { PresMovement } from './PresEnums'; import React = require('react'); -import { InkField } from '../../../../fields/InkField'; -import { RichTextField } from '../../../../fields/RichTextField'; /** * This class models the view a document added to presentation will have in the presentation. * It involves some functionality for its buttons and options. @@ -43,8 +44,11 @@ export class PresElementBox extends ViewBoxBaseComponent<FieldViewProps>() { @computed get indexInPres() { return DocListCast(this.presBox[StrCast(this.presBox.presFieldKey, 'data')]).indexOf(this.rootDoc); } // the index field is where this document is in the presBox display list (since this value is different for each presentation element, the value can't be stored on the layout template which is used by all display elements) + @computed get expandViewHeight() { + return 100; + } @computed get collapsedHeight() { - return [CollectionViewType.Tree, CollectionViewType.Stacking].includes(this.presBox._viewType as any) ? 35 : 31; + return 35; } // the collapsed height changes depending on the state of the presBox. We could store this on the presentation element template if it's used by only one presentation - but if it's shared by multiple, then this value must be looked up @computed get presStatus() { return this.presBox.presStatus; @@ -57,7 +61,7 @@ export class PresElementBox extends ViewBoxBaseComponent<FieldViewProps>() { return vpath.length > 1 ? (vpath[vpath.length - 2].ComponentView as PresBox) : undefined; } @computed get presBox() { - return (this.props.DocumentView?.().props.treeViewDoc ?? this.props.ContainingCollectionDoc)!; + return this.props.ContainingCollectionDoc!; } @computed get targetDoc() { return Cast(this.rootDoc.presentationTargetDoc, Doc, null) || this.rootDoc; @@ -66,8 +70,8 @@ export class PresElementBox extends ViewBoxBaseComponent<FieldViewProps>() { componentDidMount() { this.layoutDoc.hideLinkButton = true; this._heightDisposer = reaction( - () => [this.rootDoc.presExpandInlineButton, this.collapsedHeight], - params => (this.layoutDoc._height = NumCast(params[1]) + (Number(params[0]) ? 100 : 0)), + () => ({ expand: this.rootDoc.presExpandInlineButton, height: this.collapsedHeight }), + ({ expand, height }) => (this.layoutDoc._height = height + (expand ? this.expandViewHeight : 0)), { fireImmediately: true } ); } @@ -83,10 +87,10 @@ export class PresElementBox extends ViewBoxBaseComponent<FieldViewProps>() { @action presExpandDocumentClick = () => (this.rootDoc.presExpandInlineButton = !this.rootDoc.presExpandInlineButton); - embedHeight = (): number => 97; + embedHeight = (): number => this.collapsedHeight + this.expandViewHeight; // embedWidth = () => this.props.PanelWidth(); // embedHeight = () => Math.min(this.props.PanelWidth() - 20, this.props.PanelHeight() - this.collapsedHeight); - embedWidth = (): number => this.props.PanelWidth() - 35; + embedWidth = (): number => this.props.PanelWidth() / 2; styleProvider = (doc: Doc | undefined, props: Opt<DocumentViewProps>, property: string): any => { if (property === StyleProp.Opacity) return 1; return this.props.styleProvider?.(doc, props, property); @@ -97,35 +101,35 @@ export class PresElementBox extends ViewBoxBaseComponent<FieldViewProps>() { */ @computed get renderEmbeddedInline() { return !this.rootDoc.presExpandInlineButton || !this.targetDoc ? null : ( - <div className="presItem-embedded" style={{ height: this.embedHeight(), width: this.embedWidth() }}> + <div className="presItem-embedded" style={{ height: this.embedHeight(), width: '50%' }}> <DocumentView Document={this.rootDoc} DataDoc={undefined} //this.targetDoc[DataSym] !== this.targetDoc && this.targetDoc[DataSym]} + PanelWidth={this.embedWidth} + PanelHeight={this.embedHeight} + isContentActive={this.props.isContentActive} styleProvider={this.styleProvider} + hideLinkButton={true} + ScreenToLocalTransform={Transform.Identity} + renderDepth={this.props.renderDepth + 1} docViewPath={returnEmptyDoclist} + docFilters={this.props.docFilters} + docRangeFilters={this.props.docRangeFilters} + searchFilterDocs={this.props.searchFilterDocs} + ContainingCollectionView={undefined} + ContainingCollectionDoc={undefined} rootSelected={returnTrue} addDocument={returnFalse} removeDocument={returnFalse} - isContentActive={this.props.isContentActive} - addDocTab={returnFalse} - pinToPres={returnFalse} fitContentsToBox={returnTrue} - PanelWidth={this.embedWidth} - PanelHeight={this.embedHeight} - ScreenToLocalTransform={Transform.Identity} moveDocument={this.props.moveDocument!} - renderDepth={this.props.renderDepth + 1} focus={DocUtils.DefaultFocus} whenChildContentsActiveChanged={returnFalse} + addDocTab={returnFalse} + pinToPres={returnFalse} bringToFront={returnFalse} - docFilters={this.props.docFilters} - docRangeFilters={this.props.docRangeFilters} - searchFilterDocs={this.props.searchFilterDocs} - ContainingCollectionView={undefined} - ContainingCollectionDoc={undefined} - hideLinkButton={true} /> - <div className="presItem-embeddedMask" /> + {/* <div className="presItem-embeddedMask" /> */} </div> ); } @@ -142,7 +146,6 @@ export class PresElementBox extends ViewBoxBaseComponent<FieldViewProps>() { this.presExpandDocumentClick(); }}> <div className="presItem-groupNum">{`${ind + 1}.`}</div> - {/* style={{ maxWidth: showMore ? (toolbarWidth - 195) : toolbarWidth - 105, cursor: isSelected ? 'text' : 'grab' }} */} <div className="presItem-name"> <EditableView ref={this._titleRef} @@ -206,8 +209,8 @@ export class PresElementBox extends ViewBoxBaseComponent<FieldViewProps>() { const dragData = new DragManager.DocumentDragData(this.presBoxView?.sortArray() ?? []); if (!dragData.draggedDocuments.length) dragData.draggedDocuments.push(this.rootDoc); dragData.dropAction = 'move'; - dragData.treeViewDoc = this.props.docViewPath().lastElement()?.props.treeViewDoc; - dragData.moveDocument = this.props.docViewPath().lastElement()?.props.moveDocument; + dragData.treeViewDoc = this.presBox._viewType === CollectionViewType.Tree ? this.props.ContainingCollectionDoc : undefined; // this.props.DocumentView?.()?.props.treeViewDoc; + dragData.moveDocument = this.props.moveDocument; const dragItem: HTMLElement[] = []; if (dragArray.length === 1) { const doc = this._itemRef.current || dragArray[0]; @@ -304,7 +307,22 @@ export class PresElementBox extends ViewBoxBaseComponent<FieldViewProps>() { */ @undoBatch @action - updateView = (targetDoc: Doc, activeItem: Doc) => { + updateCapturedContainerLayout = (targetDoc: Doc, activeItem: Doc) => { + activeItem.presX = NumCast(targetDoc.x); + activeItem.presY = NumCast(targetDoc.y); + activeItem.presRot = NumCast(targetDoc.rotation); + activeItem.presWidth = NumCast(targetDoc.width); + activeItem.presHeight = NumCast(targetDoc.height); + }; + /** + * Method called for updating the view of the currently selected document + * + * @param targetDoc + * @param activeItem + */ + @undoBatch + @action + updateCapturedViewContents = (targetDoc: Doc, activeItem: Doc) => { switch (targetDoc.type) { case DocumentType.PDF: case DocumentType.WEB: @@ -312,11 +330,11 @@ export class PresElementBox extends ViewBoxBaseComponent<FieldViewProps>() { const scroll = targetDoc._scrollTop; activeItem.presPinViewScroll = scroll; if (targetDoc.type === DocumentType.RTF) { - activeItem.presData = targetDoc.text instanceof RichTextField ? targetDoc.text[Copy]() : targetDoc.text; + activeItem.presData = targetDoc[Doc.LayoutFieldKey(targetDoc)] instanceof RichTextField ? (targetDoc[Doc.LayoutFieldKey(targetDoc)] as RichTextField)[Copy]() : targetDoc.text; } break; case DocumentType.INK: - activeItem.presData = targetDoc.data instanceof InkField ? targetDoc.data[Copy]() : targetDoc.data; + activeItem.presData = targetDoc[Doc.LayoutFieldKey(targetDoc)] instanceof InkField ? (targetDoc[Doc.LayoutFieldKey(targetDoc)] as InkField)[Copy]() : targetDoc.data; break; case DocumentType.VID: case DocumentType.AUDIO: @@ -326,20 +344,23 @@ export class PresElementBox extends ViewBoxBaseComponent<FieldViewProps>() { const clipWidth = targetDoc._clipWidth; activeItem.presPinClipWidth = clipWidth; break; + case DocumentType.COL: + activeItem.presPinLayoutData = new List<string>(DocListCast(targetDoc[Doc.LayoutFieldKey(targetDoc)]).map(d => JSON.stringify({ id: d[Id], x: NumCast(d.x), y: NumCast(d.y), w: NumCast(d._width), h: NumCast(d._height) }))); default: - const x = targetDoc._panX; - const y = targetDoc._panY; - const scale = targetDoc._viewScale; - activeItem.presPinViewX = x; - activeItem.presPinViewY = y; - activeItem.presPinViewScale = scale; + const bestView = DocumentManager.Instance.getFirstDocumentView(targetDoc); + if (activeItem.presPinViewBounds && bestView) { + const bounds = MarqueeView.CurViewBounds(targetDoc, bestView.props.PanelWidth(), bestView.props.PanelHeight()); + activeItem.presPinView = true; + activeItem.presPinViewScale = NumCast(targetDoc._viewScale, 1); + activeItem.presPinViewX = bounds.left + bounds.width / 2; + activeItem.presPinViewY = bounds.top + bounds.height / 2; + activeItem.presPinViewBounds = new List<number>([bounds.left, bounds.top, bounds.left + bounds.width, bounds.top + bounds.height]); + } else { + activeItem.presPinViewX = targetDoc._panX; + activeItem.presPinViewY = targetDoc._panY; + activeItem.presPinViewScale = targetDoc._viewScale; + } } - - activeItem.presX = NumCast(targetDoc.x); - activeItem.presY = NumCast(targetDoc.y); - activeItem.presRot = NumCast(targetDoc.jitterRotation); - activeItem.presWidth = NumCast(targetDoc.width); - activeItem.presHeight = NumCast(targetDoc.height); }; @computed get recordingIsInOverlay() { @@ -446,16 +467,90 @@ export class PresElementBox extends ViewBoxBaseComponent<FieldViewProps>() { return width; } + @computed get presButtons() { + const presBox: Doc = this.presBox; //presBox + const presBoxColor: string = StrCast(presBox._backgroundColor); + const presColorBool: boolean = presBoxColor ? presBoxColor !== Colors.WHITE && presBoxColor !== 'transparent' : false; + const targetDoc: Doc = this.targetDoc; + const activeItem: Doc = this.rootDoc; + + const items: JSX.Element[] = []; + if (activeItem.presPinLayout) { + items.push( + <Tooltip key="slide" title={<div className="dash-tooltip">Update captured doc layout</div>}> + <div className="slideButton" onClick={() => this.updateCapturedContainerLayout(targetDoc, activeItem)} style={{ fontWeight: 700, display: 'flex' }}> + L + </div> + </Tooltip> + ); + } + if (activeItem.presPinData || activeItem.presPinView) { + items.push( + <Tooltip key="flex" title={<div className="dash-tooltip">Update captured doc content</div>}> + <div className="slideButton" onClick={() => this.updateCapturedViewContents(targetDoc, activeItem)} style={{ fontWeight: 700, display: 'flex' }}> + C + </div> + </Tooltip> + ); + } + if (!Doc.noviceMode) { + items.push( + <Tooltip key="slash" title={<div className="dash-tooltip">{this.recordingIsInOverlay ? 'Hide Recording' : `${PresElementBox.videoIsRecorded(activeItem) ? 'Show' : 'Start'} recording`}</div>}> + <div className="slideButton" onClick={e => (this.recordingIsInOverlay ? this.hideRecording(e, true) : this.startRecording(e, activeItem))} style={{ fontWeight: 700 }}> + <FontAwesomeIcon icon={`video${this.recordingIsInOverlay ? '-slash' : ''}`} onPointerDown={e => e.stopPropagation()} /> + </div> + </Tooltip> + ); + } + if (this.indexInPres === 0) { + items.push( + <Tooltip key="arrow" title={<div className="dash-tooltip">{activeItem.groupWithUp ? 'Ungroup' : 'Group with up'}</div>}> + <div + className="slideButton" + onClick={() => (activeItem.groupWithUp = !activeItem.groupWithUp)} + style={{ + zIndex: 1000 - this.indexInPres, + fontWeight: 700, + backgroundColor: activeItem.groupWithUp ? (presColorBool ? presBoxColor : Colors.MEDIUM_BLUE) : undefined, + height: activeItem.groupWithUp ? 53 : 18, + transform: activeItem.groupWithUp ? 'translate(0, -17px)' : undefined, + }}> + <div style={{ transform: activeItem.groupWithUp ? 'rotate(180deg) translate(0, -17.5px)' : 'rotate(0deg)' }}> + <FontAwesomeIcon icon={'arrow-up'} onPointerDown={e => e.stopPropagation()} /> + </div> + </div> + </Tooltip> + ); + } + items.push( + <Tooltip key="eye" title={<div className="dash-tooltip">{this.rootDoc.presExpandInlineButton ? 'Minimize' : 'Expand'}</div>}> + <div + className="slideButton" + onClick={e => { + e.stopPropagation(); + this.presExpandDocumentClick(); + }}> + <FontAwesomeIcon icon={this.rootDoc.presExpandInlineButton ? 'eye-slash' : 'eye'} onPointerDown={e => e.stopPropagation()} /> + </div> + </Tooltip> + ); + items.push( + <Tooltip key="trash" title={<div className="dash-tooltip">Remove from presentation</div>}> + <div className={'slideButton'} onClick={this.removeItem}> + <FontAwesomeIcon icon={'trash'} onPointerDown={e => e.stopPropagation()} /> + </div> + </Tooltip> + ); + return items; + } + @computed get mainItem() { const isSelected: boolean = this.selectedArray?.has(this.rootDoc) ? true : false; const isCurrent: boolean = this.presBox._itemIndex === this.indexInPres; - const toolbarWidth: number = this.toolbarWidth; - const showMore: boolean = this.toolbarWidth >= 300; const miniView: boolean = this.toolbarWidth <= 110; const presBox: Doc = this.presBox; //presBox const presBoxColor: string = StrCast(presBox._backgroundColor); const presColorBool: boolean = presBoxColor ? presBoxColor !== Colors.WHITE && presBoxColor !== 'transparent' : false; - const targetDoc: Doc = this.targetDoc; const activeItem: Doc = this.rootDoc; return ( @@ -466,6 +561,10 @@ export class PresElementBox extends ViewBoxBaseComponent<FieldViewProps>() { style={{ backgroundColor: presColorBool ? (isSelected ? 'rgba(250,250,250,0.3)' : 'transparent') : isSelected ? Colors.LIGHT_BLUE : 'transparent', opacity: this._dragging ? 0.3 : 1, + paddingLeft: NumCast(this.layoutDoc._xPadding, this.props.xPadding), + paddingRight: NumCast(this.layoutDoc._xPadding, this.props.xPadding), + paddingTop: NumCast(this.layoutDoc._yPadding, this.props.yPadding), + paddingBottom: NumCast(this.layoutDoc._yPadding, this.props.yPadding), }} onClick={e => { e.stopPropagation(); @@ -489,6 +588,7 @@ export class PresElementBox extends ViewBoxBaseComponent<FieldViewProps>() { ref={this._dragRef} className={`presItem-slide ${isCurrent ? 'active' : ''}`} style={{ + display: 'infline-block', backgroundColor: this.props.styleProvider?.(this.layoutDoc, this.props, StyleProp.BackgroundColor), //boxShadow: presBoxColor && presBoxColor !== 'white' && presBoxColor !== 'transparent' ? (isCurrent ? '0 0 0px 1.5px' + presBoxColor : undefined) : undefined, border: presBoxColor && presBoxColor !== 'white' && presBoxColor !== 'transparent' ? (isCurrent ? presBoxColor + ' solid 2.5px' : undefined) : undefined, @@ -496,8 +596,9 @@ export class PresElementBox extends ViewBoxBaseComponent<FieldViewProps>() { <div className="presItem-name" style={{ + display: 'inline-flex', pointerEvents: isSelected ? undefined : 'none', - maxWidth: showMore ? toolbarWidth - 195 : toolbarWidth - 105, + width: `calc(100% ${this.rootDoc.presExpandInlineButton ? '- 50%' : ''} - ${this.presButtons.length * 22}px`, cursor: isSelected ? 'text' : 'grab', }}> <div>{`${this.indexInPres + 1}. `}</div> @@ -505,49 +606,8 @@ export class PresElementBox extends ViewBoxBaseComponent<FieldViewProps>() { </div> {/* <Tooltip title={<><div className="dash-tooltip">{"Movement speed"}</div></>}><div className="presItem-time" style={{ display: showMore ? "block" : "none" }}>{this.transition}</div></Tooltip> */} {/* <Tooltip title={<><div className="dash-tooltip">{"Duration"}</div></>}><div className="presItem-time" style={{ display: showMore ? "block" : "none" }}>{this.duration}</div></Tooltip> */} - <div className="presItem-slideButtons"> - <Tooltip title={<div className="dash-tooltip">Update view</div>}> - <div className="slideButton" onClick={() => this.updateView(targetDoc, activeItem)} style={{ fontWeight: 700, display: activeItem.presPinView ? 'flex' : 'none' }}> - V - </div> - </Tooltip> - {!Doc.noviceMode && <Tooltip title={<div className="dash-tooltip">{this.recordingIsInOverlay ? 'Hide Recording' : `${PresElementBox.videoIsRecorded(activeItem) ? 'Show' : 'Start'} recording`}</div>}> - <div className="slideButton" onClick={e => (this.recordingIsInOverlay ? this.hideRecording(e, true) : this.startRecording(e, activeItem))} style={{ fontWeight: 700 }}> - <FontAwesomeIcon icon={`video${this.recordingIsInOverlay ? '-slash' : ''}`} onPointerDown={e => e.stopPropagation()} /> - </div> - </Tooltip>} - <Tooltip title={<div className="dash-tooltip">{activeItem.groupWithUp ? 'Ungroup' : 'Group with up'}</div>}> - <div - className="slideButton" - onClick={() => (activeItem.groupWithUp = !activeItem.groupWithUp)} - style={{ - display: this.indexInPres === 0 ? 'none' : '', - zIndex: 1000 - this.indexInPres, - fontWeight: 700, - backgroundColor: activeItem.groupWithUp ? (presColorBool ? presBoxColor : Colors.MEDIUM_BLUE) : undefined, - height: activeItem.groupWithUp ? 53 : 18, - transform: activeItem.groupWithUp ? 'translate(0, -17px)' : undefined, - }}> - <div style={{ transform: activeItem.groupWithUp ? 'rotate(180deg) translate(0, -17.5px)' : 'rotate(0deg)' }}> - <FontAwesomeIcon icon={'arrow-up'} onPointerDown={e => e.stopPropagation()} /> - </div> - </div> - </Tooltip> - <Tooltip title={<div className="dash-tooltip">{this.rootDoc.presExpandInlineButton ? 'Minimize' : 'Expand'}</div>}> - <div - className="slideButton" - onClick={e => { - e.stopPropagation(); - this.presExpandDocumentClick(); - }}> - <FontAwesomeIcon icon={this.rootDoc.presExpandInlineButton ? 'eye-slash' : 'eye'} onPointerDown={e => e.stopPropagation()} /> - </div> - </Tooltip> - <Tooltip title={<div className="dash-tooltip">Remove from presentation</div>}> - <div className={'slideButton'} onClick={this.removeItem}> - <FontAwesomeIcon icon={'trash'} onPointerDown={e => e.stopPropagation()} /> - </div> - </Tooltip> + <div className="presItem-slideButtons" style={{ position: 'absolute', right: 0 }}> + {...this.presButtons} </div> {this.renderEmbeddedInline} </div> |