aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorbobzel <zzzman@gmail.com>2024-10-10 10:03:03 -0400
committerbobzel <zzzman@gmail.com>2024-10-10 10:03:03 -0400
commitf0f1d04df56eb95a6d28dcbeab5071bd681baa15 (patch)
tree5ddabc3d5760d028660ada2b8240111246f4b8f2
parente9bf4605675857ee9e822c1051107fe86dc1bc16 (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
-rw-r--r--src/client/views/collections/CollectionCardDeckView.tsx56
-rw-r--r--src/client/views/collections/FlashcardPracticeUI.tsx4
-rw-r--r--src/client/views/collections/TreeView.tsx4
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 = [];