From 66f904921ef519e1b54cb013ea7fafc640ae3dc7 Mon Sep 17 00:00:00 2001 From: aidahosa1 Date: Tue, 19 Mar 2024 16:21:34 -0400 Subject: working on implementing card logic --- .../views/collections/CollectionCardDeckView.tsx | 281 +++++++++++---------- 1 file changed, 151 insertions(+), 130 deletions(-) (limited to 'src/client/views/collections/CollectionCardDeckView.tsx') diff --git a/src/client/views/collections/CollectionCardDeckView.tsx b/src/client/views/collections/CollectionCardDeckView.tsx index feb9e61cc..e35f7b421 100644 --- a/src/client/views/collections/CollectionCardDeckView.tsx +++ b/src/client/views/collections/CollectionCardDeckView.tsx @@ -1,164 +1,185 @@ -import { action, computed, IReactionDisposer, makeObservable } from 'mobx'; +import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; +import { computed, makeObservable } from 'mobx'; import { observer } from 'mobx-react'; import * as React from 'react'; +import { Utils, emptyFunction, returnFalse, returnZero } from '../../../Utils'; import { Doc, DocListCast } from '../../../fields/Doc'; -import { ScriptField } from '../../../fields/ScriptField'; -import { NumCast, StrCast } from '../../../fields/Types'; -import { emptyFunction, returnFalse, setupMoveUpEvents } from '../../../Utils'; -import { DocUtils } from '../../documents/Documents'; +import { Id } from '../../../fields/FieldSymbols'; +import { DocCast, NumCast, ScriptCast, StrCast } from '../../../fields/Types'; +import { DocumentType } from '../../documents/DocumentTypes'; +import { DragManager } from '../../util/DragManager'; import { SelectionManager } from '../../util/SelectionManager'; -import { undoBatch, UndoManager } from '../../util/UndoManager'; -import { OpenWhere } from '../nodes/DocumentView'; -import { computePassLayout, computeStarburstLayout, computeCardDeckLayout } from './collectionFreeForm'; -import { CollectionFreeFormView } from './collectionFreeForm/CollectionFreeFormView'; -import './CollectionPileView.scss'; +import { StyleProp } from '../StyleProvider'; +import { DocumentView } from '../nodes/DocumentView'; +import { FocusViewOptions } from '../nodes/FieldView'; +import './CollectionCarousel3DView.scss'; import { CollectionSubView } from './CollectionSubView'; -import { dropActionType } from '../../util/DragManager'; - +const { default: { CAROUSEL3D_CENTER_SCALE, CAROUSEL3D_SIDE_SCALE, CAROUSEL3D_TOP } } = require('../global/globalCssVariables.module.scss'); // prettier-ignore @observer export class CollectionCardView extends CollectionSubView() { - _originalChrome: any = ''; - _disposers: { [name: string]: IReactionDisposer } = {}; - + @computed get scrollSpeed() { + return this.layoutDoc._autoScrollSpeed ? NumCast(this.layoutDoc._autoScrollSpeed) : 1000; //default scroll speed + } constructor(props: any) { super(props); makeObservable(this); } - componentDidMount() { - if (this.layoutEngine() !== computePassLayout.name && this.layoutEngine() !== computeCardDeckLayout.name) { - this.Document._freeform_cardEngine = computePassLayout.name; - } - this._originalChrome = this.layoutDoc._chromeHidden; - this.layoutDoc._chromeHidden = true; - } + private _dropDisposer?: DragManager.DragDropDisposer; + componentWillUnmount() { - this.layoutDoc._chromeHidden = this._originalChrome; - Object.values(this._disposers).forEach(disposer => disposer?.()); + this._dropDisposer?.(); } - layoutEngine = () => StrCast(this.Document._freeform_cardEngine); - - @undoBatch - addCardDoc = (doc: Doc | Doc[]) => { - (doc instanceof Doc ? [doc] : doc).map(d => DocUtils.iconify(d)); - return this._props.addDocument?.(doc) || false; + protected createDashEventsTarget = (ele: HTMLDivElement | null) => { + this._dropDisposer?.(); + if (ele) { + this._dropDisposer = DragManager.MakeDropTarget(ele, this.onInternalDrop.bind(this), this.layoutDoc); + } }; - @undoBatch - removeCardDoc = (doc: Doc | Doc[], targetCollection: Doc | undefined, addDoc: (doc: Doc | Doc[]) => boolean) => { - (doc instanceof Doc ? [doc] : doc).forEach(d => Doc.deiconifyView(d)); - const ret = this._props.moveDocument?.(doc, targetCollection, addDoc) || false; - if (ret && !DocListCast(this.dataDoc[this.fieldKey ?? 'data']).length) this.DocumentView?.()._props.removeDocument?.(this.Document); - return ret; + centerScale = Number(CAROUSEL3D_CENTER_SCALE); + panelWidth = () => this._props.PanelWidth() / 3; + panelHeight = () => this._props.PanelHeight() * Number(CAROUSEL3D_SIDE_SCALE); + onChildDoubleClick = () => ScriptCast(this.layoutDoc.onChildDoubleClick); + isContentActive = () => this._props.isSelected() || this._props.isContentActive() || this._props.isAnyChildContentActive(); + isChildContentActive = () => (this.isContentActive() ? true : false); + childScreenToLocal = () => + this._props // document's left is the panel shifted by the doc's index * panelWidth/#docs. But it scales by centerScale around its center, so it's left moves left by the distance of the left from the center (panelwidth/2) * the scale delta (centerScale-1) + .ScreenToLocalTransform() // the top behaves the same way ecept it's shifted by the 'top' amount specified for the panel in css and then by the scale factor. + .translate(-this.panelWidth() + ((this.centerScale - 1) * this.panelWidth()) / 2, -((Number(CAROUSEL3D_TOP) / 100) * this._props.PanelHeight()) + ((this.centerScale - 1) * this.panelHeight()) / 2) + .scale(1 / this.centerScale); + + focus = (anchor: Doc, options: FocusViewOptions) => { + const docs = DocListCast(this.Document[this.fieldKey ?? Doc.LayoutFieldKey(this.Document)]); + if (anchor.type !== DocumentType.CONFIG && !docs.includes(anchor)) return; + options.didMove = true; + const target = DocCast(anchor.annotationOn) ?? anchor; + const index = docs.indexOf(target); + index !== -1 && (this.layoutDoc._carousel_index = index); //if index is not -1, then assign index to this.layoutDoc._carousel_index + return undefined; }; - @computed get toggleIcon() { - return ScriptField.MakeScript('documentView.iconify()', { documentView: 'any' }); - } - @computed get contentEvents() { - const isCard = this.layoutEngine() === computeCardDeckLayout.name; - return this._props.isContentActive() && isCard ? undefined : 'none'; + + @computed get content() { + const currentIndex = NumCast(this.layoutDoc._carousel_index); + const displayDoc = (childPair: { layout: Doc; data: Doc }) => { + return ( + + ); + }; + + return this.childLayoutPairs.map((childPair, index) => { + return ( +
+ {displayDoc(childPair)} +
+ ); + }); } - // returns the contents of the cardSpread in a CollectionFreeFormView - @computed get contents() { + changeSlide = (direction: number) => { + SelectionManager.DeselectAll(); + this.layoutDoc._carousel_index = (NumCast(this.layoutDoc._carousel_index) + direction + this.childLayoutPairs.length) % this.childLayoutPairs.length; + }; + + onArrowClick = (direction: number) => { + this.changeSlide(direction); + !this.layoutDoc.autoScrollOn && (this.layoutDoc.showScrollButton = direction === 1 ? 'fwd' : 'back'); // while autoscroll is on, keep the other autoscroll button hidden + !this.layoutDoc.autoScrollOn && this.fadeScrollButton(); // keep pause button visible while autoscroll is on + }; + + interval?: number; + startAutoScroll = (direction: number) => { + this.interval = window.setInterval(() => { + this.changeSlide(direction); + }, this.scrollSpeed); + }; + + stopAutoScroll = () => { + window.clearInterval(this.interval); + this.interval = undefined; + this.fadeScrollButton(); + }; + + toggleAutoScroll = (direction: number) => { + this.layoutDoc.autoScrollOn = this.layoutDoc.autoScrollOn ? false : true; + this.layoutDoc.autoScrollOn ? this.startAutoScroll(direction) : this.stopAutoScroll(); + }; + + fadeScrollButton = () => { + window.setTimeout(() => { + !this.layoutDoc.autoScrollOn && (this.layoutDoc.showScrollButton = 'none'); //fade away after 1.5s if it's not clicked. + }, 1500); + }; + + @computed get buttons() { return ( -
- +
+
this.onArrowClick(-1)} /> +
this.onArrowClick(1)} /> + {/* {this.autoScrollButton} */}
); } - // // toggles the pileup between starburst to compact - // toggleStarburst = action(() => { - // this.layoutDoc._freeform_scale = undefined; - // if (this.layoutEngine() === computeStarburstLayout.name) { - // if (NumCast(this.layoutDoc._width) !== NumCast(this.Document._starburstDiameter, 500)) { - // this.Document._starburstDiameter = NumCast(this.layoutDoc._width); - // } - // const defaultSize = 110; - // this.Document.x = NumCast(this.Document.x) + NumCast(this.layoutDoc._width) / 2 - NumCast(this.layoutDoc._freeform_pileWidth, defaultSize) / 2; - // this.Document.y = NumCast(this.Document.y) + NumCast(this.layoutDoc._height) / 2 - NumCast(this.layoutDoc._freeform_pileHeight, defaultSize) / 2; - // this.layoutDoc._width = NumCast(this.layoutDoc._freeform_pileWidth, defaultSize); - // this.layoutDoc._height = NumCast(this.layoutDoc._freeform_pileHeight, defaultSize); - // DocUtils.pileup(this.childDocs, undefined, undefined, NumCast(this.layoutDoc._width) / 2, false); - // this.layoutDoc._freeform_panX = 0; - // this.layoutDoc._freeform_panY = -10; - // this.Document._freeform_pileEngine = computePassLayout.name; - // } else { - // const defaultSize = NumCast(this.Document._starburstDiameter, 400); - // this.Document.x = NumCast(this.Document.x) + NumCast(this.layoutDoc._width) / 2 - defaultSize / 2; - // this.Document.y = NumCast(this.Document.y) + NumCast(this.layoutDoc._height) / 2 - defaultSize / 2; - // this.layoutDoc._freeform_pileWidth = NumCast(this.layoutDoc._width); - // this.layoutDoc._freeform_pileHeight = NumCast(this.layoutDoc._height); - // this.layoutDoc._freeform_panX = this.layoutDoc._freeform_panY = 0; - // this.layoutDoc._width = this.layoutDoc._height = defaultSize; - // this.layoutDoc.background; - // this.Document._freeform_pileEngine = computeStarburstLayout.name; - // } - // }); - - // for dragging documents out of the pileup view - _undoBatch: UndoManager.Batch | undefined; - pointerDown = (e: React.PointerEvent) => { - let dist = 0; - setupMoveUpEvents( - this, - e, - (e: PointerEvent, down: number[], delta: number[]) => { - if (this.layoutEngine() === 'pass' && this.childDocs.length && e.shiftKey) { - dist += Math.sqrt(delta[0] * delta[0] + delta[1] * delta[1]); - if (dist > 100) { - if (!this._undoBatch) { - this._undoBatch = UndoManager.StartBatch('layout pile'); - } - const doc = this.childDocs[0]; - doc.x = e.clientX; - doc.y = e.clientY; - this._props.addDocTab(doc, OpenWhere.inParentFromScreen) && (this._props.removeDocument?.(doc) || false); - dist = 0; - } - } - return false; - }, - () => { - this._undoBatch?.end(); - this._undoBatch = undefined; - }, - emptyFunction, - e.shiftKey && this.layoutEngine() === computePassLayout.name, - this.layoutEngine() === computePassLayout.name && e.shiftKey - ); // this sets _doubleTap - }; + @computed get autoScrollButton() { + const whichButton = this.layoutDoc.showScrollButton; + return ( + <> +
this.toggleAutoScroll(-1)}> + {this.layoutDoc.autoScrollOn ? : } +
+
this.toggleAutoScroll(1)}> + {this.layoutDoc.autoScrollOn ? : } +
+ + ); + } - // onClick for toggling the pileup view - // @undoBatch - // onClick = (e: React.MouseEvent) => { - // if (e.button === 0) { - // SelectionManager.DeselectAll(); - // this.toggleStarburst(); - // e.stopPropagation(); - // } - // }; + @computed get dots() { + return this.childLayoutPairs.map((_child, index) =>
(this.layoutDoc._carousel_index = index)} />); + } + @computed get translateX() { + const index = NumCast(this.layoutDoc._carousel_index); + return this.panelWidth() * (1 - index); + } render() { return ( -
- {this.contents} +
+
+ {this.content} +
+ {this.buttons} +
{this.dots}
); } + + } -- cgit v1.2.3-70-g09d2