diff options
author | bobzel <zzzman@gmail.com> | 2024-10-10 10:03:03 -0400 |
---|---|---|
committer | bobzel <zzzman@gmail.com> | 2024-10-10 10:03:03 -0400 |
commit | f0f1d04df56eb95a6d28dcbeab5071bd681baa15 (patch) | |
tree | 5ddabc3d5760d028660ada2b8240111246f4b8f2 /src | |
parent | e9bf4605675857ee9e822c1051107fe86dc1bc16 (diff) |
tweaks to cardDeck view so that cards are activated when clicked, but not selected. This is consistent with carousel behavior and allows flashcards to behave the same way. Also added advance to nexst card for card view
Diffstat (limited to 'src')
-rw-r--r-- | src/client/views/collections/CollectionCardDeckView.tsx | 56 | ||||
-rw-r--r-- | src/client/views/collections/FlashcardPracticeUI.tsx | 4 | ||||
-rw-r--r-- | src/client/views/collections/TreeView.tsx | 4 |
3 files changed, 41 insertions, 23 deletions
diff --git a/src/client/views/collections/CollectionCardDeckView.tsx b/src/client/views/collections/CollectionCardDeckView.tsx index 8807462c3..810b7b33c 100644 --- a/src/client/views/collections/CollectionCardDeckView.tsx +++ b/src/client/views/collections/CollectionCardDeckView.tsx @@ -2,7 +2,7 @@ import { IReactionDisposer, ObservableMap, action, computed, makeObservable, obs import { observer } from 'mobx-react'; import { computedFn } from 'mobx-utils'; import * as React from 'react'; -import { ClientUtils, DashColor, imageUrlToBase64, returnFalse, returnZero } from '../../../ClientUtils'; +import { ClientUtils, DashColor, imageUrlToBase64, returnFalse, returnNever, returnZero } from '../../../ClientUtils'; import { Doc } from '../../../fields/Doc'; import { DocData } from '../../../fields/DocSymbols'; import { Id } from '../../../fields/FieldSymbols'; @@ -18,10 +18,12 @@ import { Transform } from '../../util/Transform'; import { undoable } from '../../util/UndoManager'; import { StyleProp } from '../StyleProp'; import { TagItem } from '../TagsView'; -import { DocumentView } from '../nodes/DocumentView'; +import { DocumentView, DocumentViewProps } from '../nodes/DocumentView'; import { GPTPopup, GPTPopupMode } from '../pdf/GPTPopup/GPTPopup'; import './CollectionCardDeckView.scss'; import { CollectionSubView, SubCollectionViewProps } from './CollectionSubView'; +import { emptyFunction } from '../../../Utils'; +import { ScriptField } from '../../../fields/ScriptField'; enum cardSortings { Time = 'time', @@ -45,12 +47,14 @@ export class CollectionCardView extends CollectionSubView() { private _disposers: { [key: string]: IReactionDisposer } = {}; private _textToDoc = new Map<string, Doc>(); private _dropped = false; // set when a card doc has just moved and the drop method has been called - prevents the pointerUp method from hiding doc decorations (which needs to be done when clicking on a card to animate it to front/center) + private _clickScript = () => ScriptField.MakeScript('scriptContext._curDoc=this', { scriptContext: 'any' })!; @observable _forceChildXf = 0; @observable _hoveredNodeIndex = -1; @observable _docRefs = new ObservableMap<Doc, DocumentView>(); @observable _maxRowCount = 10; @observable _docDraggedIndex: number = -1; + @observable _curDoc: Doc | undefined = undefined; constructor(props: SubCollectionViewProps) { super(props); @@ -131,10 +135,10 @@ export class CollectionCardView extends CollectionSubView() { /** * When in quiz mode, randomly selects a document */ - quizMode = () => { + quizMode = action(() => { const randomIndex = Math.floor(Math.random() * this.childDocs.length); - DocumentView.getDocumentView(this.childDocs[randomIndex])?.select(false); - }; + this._curDoc = this.childDocs[randomIndex]; + }); /** * Number of rows of cards to be rendered @@ -336,7 +340,7 @@ export class CollectionCardView extends CollectionSubView() { (doc: Doc) => () => this._props.isContentActive?.() === false ? false - : this._props.isDocumentActive?.() && this.curDoc() === doc + : this._props.isDocumentActive?.() && this._curDoc === doc ? true : this._props.childDocumentsActive?.() === false || this.Document.childDocumentsActive === false ? false @@ -360,6 +364,9 @@ export class CollectionCardView extends CollectionSubView() { isDocumentActive={this._props.childDocumentsActive?.() || this.Document._childDocumentsActive ? this._props.isDocumentActive : this.isContentActive} PanelWidth={this.childPanelWidth} PanelHeight={this.childPanelHeight} + waitForDoubleClickToClick={returnNever} + scriptContext={this} + onClickScript={this._curDoc === doc ? undefined : this._clickScript} dontCenter="y" // Don't center it vertically, because the grid it's in is already doing that and we don't want to do it twice. dragAction={(this.Document.childDragAction ?? this._props.childDragAction) as dropActionType} showTags={BoolCast(this.layoutDoc.showChildTags)} @@ -553,7 +560,7 @@ export class CollectionCardView extends CollectionSubView() { cardPointerUp = action((doc: Doc) => { // if a card doc has just moved, or a card is selected and in front, then ignore this event - if (this.isSelected(doc) || this._dropped) { + if (this._curDoc === doc || this._dropped) { this._dropped = false; } else { // otherwise, turn off documentDecorations becase we're in a selection transition and want to avoid artifacts. @@ -581,9 +588,8 @@ export class CollectionCardView extends CollectionSubView() { return this.sortedDocs.map((doc, index) => { const calcRowIndex = this.overflowIndexCalc(index); const amCards = this.overflowAmCardsCalc(index); - const view = DocumentView.getDocumentView(doc, this.DocumentView?.()); - const childScreenToLocal = this.childScreenToLocal(doc, index, calcRowIndex, !!view?.IsContentActive, amCards); + const childScreenToLocal = this.childScreenToLocal(doc, index, calcRowIndex, doc === this._curDoc, amCards); const translateIfSelected = () => { const indexInRow = index % this._maxRowCount; @@ -598,15 +604,15 @@ export class CollectionCardView extends CollectionSubView() { return ( <div key={doc[Id]} - className={`card-item${view?.IsContentActive ? '-active' : this.isAnyChildContentActive() ? '-inactive' : ''}`} + className={`card-item${doc === this._curDoc ? '-active' : this.isAnyChildContentActive() ? '-inactive' : ''}`} onPointerUp={() => this.cardPointerUp(doc)} style={{ width: this.childPanelWidth(), height: 'max-content', - transform: `translateY(${this.calculateTranslateY(!!view?.IsContentActive, index, amCards, calcRowIndex)}px) - translateX(calc(${view?.IsContentActive ? translateIfSelected() : 0}% + ${this.translateOverflowX(index, amCards)}px)) - rotate(${!view?.IsContentActive ? this.rotate(amCards, calcRowIndex) : 0}deg) - scale(${view?.IsContentActive ? `${Math.min(hscale, vscale) * 100}%` : this._hoveredNodeIndex === index ? 1.1 : 1})`, + transform: `translateY(${this.calculateTranslateY(doc === this._curDoc, index, amCards, calcRowIndex)}px) + translateX(calc(${doc === this._curDoc ? translateIfSelected() : 0}% + ${this.translateOverflowX(index, amCards)}px)) + rotate(${doc !== this._curDoc ? this.rotate(amCards, calcRowIndex) : 0}deg) + scale(${doc === this._curDoc ? `${Math.min(hscale, vscale) * 100}%` : this._hoveredNodeIndex === index ? 1.1 : 1})`, }} // prettier-ignore onPointerEnter={() => this.setHoveredNodeIndex(index)} onPointerLeave={() => this.setHoveredNodeIndex(-1)}> @@ -617,13 +623,16 @@ export class CollectionCardView extends CollectionSubView() { } contentScreenToLocalXf = () => this._props.ScreenToLocalTransform().scale(this._props.NativeDimScaling?.() || 1); - curDoc = () => this.childCards.find(card => DocumentView.getDocumentView(card.layout, this.DocumentView?.())?.IsSelected)?.layout; - docViewProps = () => ({ + docViewProps = (): DocumentViewProps => ({ ...this._props, // isDocumentActive: this._props.childDocumentsActive?.() ? this._props.isDocumentActive : this._props.isContentActive, - isContentActive: this.isChildContentActive, + isContentActive: emptyFunction, ScreenToLocalTransform: this.contentScreenToLocalXf, }); + answered = action(() => { + this._curDoc = this.curDoc ? this.filteredChildDocs()[(this.filteredChildDocs().findIndex(this.curDoc) + 1) % (this.filteredChildDocs().length || 1)] : undefined; + }); + curDoc = () => this._curDoc; render() { const isEmpty = this.childCards.length === 0; @@ -631,6 +640,17 @@ export class CollectionCardView extends CollectionSubView() { <div className="collectionCardView-outer" ref={(ele: HTMLDivElement | null) => this.createDashEventsTarget(ele)} + onPointerDown={action(() => { + this._curDoc = undefined; + SnappingManager.SetHideDecorations(true); + setTimeout( + action(() => { + SnappingManager.SetHideDecorations(false); + this._forceChildXf++; + }), + 1000 + ); + })} onPointerLeave={action(() => (this._docDraggedIndex = -1))} onPointerMove={e => this.onPointerMove(...this._props.ScreenToLocalTransform().transformPoint(e.clientX, e.clientY))} onDrop={this.onExternalDrop.bind(this)} @@ -648,7 +668,7 @@ export class CollectionCardView extends CollectionSubView() { }}> {this.renderCards} </div> - {this.flashCardUI(this.curDoc, this.docViewProps)} + {this.flashCardUI(this.curDoc, this.docViewProps, this.answered)} </div> ); } diff --git a/src/client/views/collections/FlashcardPracticeUI.tsx b/src/client/views/collections/FlashcardPracticeUI.tsx index efa94d845..272fb81dc 100644 --- a/src/client/views/collections/FlashcardPracticeUI.tsx +++ b/src/client/views/collections/FlashcardPracticeUI.tsx @@ -107,12 +107,12 @@ export class FlashcardPracticeUI extends ObservableReactComponent<PracticeUIProp return this.practiceMode == practiceMode.PRACTICE && this._props.curDoc() ? ( <div className="FlashcardPracticeUI-practice" style={{ transform: `scale(${this._props.uiBtnScaling})`, bottom: `${this._props.practiceBtnOffset ?? this._props.sideBtnWidth}px`, height: `${this._props.sideBtnWidth}px` }}> <Tooltip title="Incorrect. View again later."> - <div key="remove" className="FlashcardPracticeUI-remove" onClick={e => setPracticeVal(e, practiceVal.MISSED)}> + <div key="remove" className="FlashcardPracticeUI-remove" onPointerDown={e => setupMoveUpEvents(this, e, returnFalse, emptyFunction, () => setPracticeVal(e, practiceVal.MISSED))}> <FontAwesomeIcon icon="xmark" color="red" size="1x" /> </div> </Tooltip> <Tooltip title="Correct"> - <div key="check" className="FlashcardPracticeUI-check" onClick={e => setPracticeVal(e, practiceVal.CORRECT)}> + <div key="check" className="FlashcardPracticeUI-check" onPointerDown={e => setupMoveUpEvents(this, e, returnFalse, emptyFunction, () => setPracticeVal(e, practiceVal.CORRECT))}> <FontAwesomeIcon icon="check" color="green" size="1x" /> </div> </Tooltip> diff --git a/src/client/views/collections/TreeView.tsx b/src/client/views/collections/TreeView.tsx index 5444a7a57..9284a36a2 100644 --- a/src/client/views/collections/TreeView.tsx +++ b/src/client/views/collections/TreeView.tsx @@ -38,7 +38,7 @@ import { CollectionView } from './CollectionView'; import { TreeSort } from './TreeSort'; import './TreeView.scss'; -// eslint-disable-next-line @typescript-eslint/no-var-requires +// eslint-disable-next-line @typescript-eslint/no-require-imports const { TREE_BULLET_WIDTH } = require('../global/globalCssVariables.module.scss'); // prettier-ignore export interface TreeViewProps { @@ -500,9 +500,7 @@ export class TreeView extends ObservableReactComponent<TreeViewProps> { !(key in ids) && doc[key] !== ComputedField.undefined && (ids[key] = key); }); - // eslint-disable-next-line no-restricted-syntax for (const key of Object.keys(ids).slice().sort()) { - // eslint-disable-next-line no-continue if (this._props.skipFields?.includes(key) || key === 'title' || key === 'treeView_Open') continue; const contents = doc[key]; let contentElement: (JSX.Element | null)[] | JSX.Element = []; |