From f0b41a82df3ce7ea9a29e8a779a1967349f5b92a Mon Sep 17 00:00:00 2001
From: bobzel <zzzman@gmail.com>
Date: Mon, 13 May 2024 10:49:06 -0400
Subject: fixed documentDecorations for cardDeck view to not lag behind
 document movement

---
 .../views/collections/CollectionCardDeckView.tsx   | 286 +++++++++------------
 1 file changed, 123 insertions(+), 163 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 bf26ad4b5..80159ae38 100644
--- a/src/client/views/collections/CollectionCardDeckView.tsx
+++ b/src/client/views/collections/CollectionCardDeckView.tsx
@@ -16,7 +16,7 @@ import { LinkManager } from '../../util/LinkManager';
 // import Card from 'react-bootstrap/Card';
 import { DocumentType } from '../../documents/DocumentTypes';
 import { forEach } from 'lodash';
-
+import { SnappingManager } from '../../util/SnappingManager';
 
 @observer
 export class CollectionCardView extends CollectionSubView() {
@@ -24,8 +24,8 @@ export class CollectionCardView extends CollectionSubView() {
 
     @observable hoveredNodeIndex = -1;
 
-    @computed get myChildLayoutPairs(){
-        return this.childLayoutPairs.filter(l => l.layout.type != DocumentType.LINK)
+    @computed get myChildLayoutPairs() {
+        return this.childLayoutPairs.filter(l => l.layout.type != DocumentType.LINK);
     }
 
     @action
@@ -64,8 +64,6 @@ export class CollectionCardView extends CollectionSubView() {
         return docs.filter(d => !SelectionManager.IsSelected(d.layout));
     };
 
-
-
     middleIndex = Math.floor(this.inactiveDocs().length / 2);
 
     constructor(props: any) {
@@ -87,19 +85,15 @@ export class CollectionCardView extends CollectionSubView() {
         }
     };
 
-
-
     childDocumentWidth = 600; // target width of a Doc...
     /**
      * how much to scale down the contents of the view so that everything will fit
      */
     @computed get fitContentScale() {
-        if (this.myChildLayoutPairs.length< this.maxRowCount){
-            length = this.myChildLayoutPairs.length
-        }
-
-        else{
-            length = this.maxRowCount
+        if (this.myChildLayoutPairs.length < this.maxRowCount) {
+            length = this.myChildLayoutPairs.length;
+        } else {
+            length = this.maxRowCount;
         }
         return (this.childDocumentWidth * length) / this._props.PanelWidth();
     }
@@ -109,10 +103,6 @@ export class CollectionCardView extends CollectionSubView() {
     isContentActive = () => this._props.isSelected() || this._props.isContentActive() || this._props.isAnyChildContentActive();
     isChildContentActive = () => (this.isContentActive() ? true : false);
 
-
-
-    
-
     rotate = (amCards: number, index: number) => {
         // console.log(amCards + "wtf")
         const possRotate = -30 + index * (30 / ((amCards - (amCards % 2)) / 2));
@@ -136,15 +126,13 @@ export class CollectionCardView extends CollectionSubView() {
         const evenOdd = amCards % 2;
         const apex = (amCards - evenOdd) / 2;
         const stepMag = 200 / ((amCards - evenOdd) / 2) + Math.abs((apex - index) * 25);
-        let rowOffset = 0
+        let rowOffset = 0;
 
-        if (realIndex > this.maxRowCount -1){
+        if (realIndex > this.maxRowCount - 1) {
             // 11 - 1 = 10
-            rowOffset = 400 * ((realIndex - (realIndex % this.maxRowCount)) / this.maxRowCount)
+            rowOffset = 400 * ((realIndex - (realIndex % this.maxRowCount)) / this.maxRowCount);
         }
 
-        
-
         // console.log('steo' + stepMag);
 
         if (evenOdd == 1 || index < apex - 1) {
@@ -168,115 +156,114 @@ export class CollectionCardView extends CollectionSubView() {
 
     translateSelected = (index: number): number => {
         // if (this.isSelected(index)) {
-            const middleOfPanel = this._props.PanelWidth() / 2;
-            const scaledNodeWidth = this.panelWidth() * 1.25;
+        const middleOfPanel = this._props.PanelWidth() / 2;
+        const scaledNodeWidth = this.panelWidth() * 1.25;
 
-            // Calculate the position of the node's left edge before scaling
-            const nodeLeftEdge = index * this.panelWidth();
-            // Find the center of the node after scaling
-            const scaledNodeCenter = nodeLeftEdge + scaledNodeWidth / 2;
+        // Calculate the position of the node's left edge before scaling
+        const nodeLeftEdge = index * this.panelWidth();
+        // Find the center of the node after scaling
+        const scaledNodeCenter = nodeLeftEdge + scaledNodeWidth / 2;
 
-            // Calculate the translation needed to align the scaled node's center with the panel's center
-            const translation = middleOfPanel - scaledNodeCenter - scaledNodeWidth - (scaledNodeWidth /4);
+        // Calculate the translation needed to align the scaled node's center with the panel's center
+        const translation = middleOfPanel - scaledNodeCenter - scaledNodeWidth - scaledNodeWidth / 4;
 
-            return translation;
+        return translation;
         // }
 
         // return 0;
     };
 
     @computed get sortedDocsType() {
-        
         const desc = BoolCast(this.layoutDoc.sortDesc);
-        let sorted = []
-        let docs = []
+        let sorted = [];
+        let docs = [];
 
-        for (let i=0; i< this.myChildLayoutPairs.length; i++){ //copying everything in childlayout pairs to sorted so that i can use the sort function without altering the original list
-            sorted[i] = this.myChildLayoutPairs[i]
+        for (let i = 0; i < this.myChildLayoutPairs.length; i++) {
+            //copying everything in childlayout pairs to sorted so that i can use the sort function without altering the original list
+            sorted[i] = this.myChildLayoutPairs[i];
         }
 
-        switch(this._props.Document.cardSort){
-            case "type":
-                 // Copy and sort documents by type 
-                return this.sort(sorted, "type", desc)
-            case "color":
-                return this.sort(sorted, "color", desc)
+        switch (this._props.Document.cardSort) {
+            case 'type':
+                // Copy and sort documents by type
+                return this.sort(sorted, 'type', desc);
+            case 'color':
+                return this.sort(sorted, 'color', desc);
             // case "links":
             //     console.log("hi")
 
-                //    let links = LinkManager.Instance.getAllRelatedLinks(this.myChildLayoutPairs[0].layout)
+            //    let links = LinkManager.Instance.getAllRelatedLinks(this.myChildLayoutPairs[0].layout)
 
-                //    console.log(links)
-                   
-                   // }
+            //    console.log(links)
 
-            case "custom":
-                console.log("hiiiii")
-                return this.sort(sorted, "custom", desc)
-            
+            // }
 
-            default:
-                docs =  this.myChildLayoutPairs
-                return {docs}
+            case 'custom':
+                console.log('hiiiii');
+                return this.sort(sorted, 'custom', desc);
 
-
-                
+            default:
+                docs = this.myChildLayoutPairs;
+                return { docs };
         }
     }
 
-    
-    
-
     hexToHsv = (hex: string): [number, number, number] => {
         if (!hex) return [0, 0, 0]; // Default to black if hex is not defined
         const r = parseInt(hex.slice(1, 3), 16) / 255;
         const g = parseInt(hex.slice(3, 5), 16) / 255;
         const b = parseInt(hex.slice(5, 7), 16) / 255;
-        const max = Math.max(r, g, b), min = Math.min(r, g, b);
+        const max = Math.max(r, g, b),
+            min = Math.min(r, g, b);
         const d = max - min;
         let h: number;
-        const s = (max === 0 ? 0 : d / max);
+        const s = max === 0 ? 0 : d / max;
         const v = max;
 
         switch (max) {
-            case min: h = 0; break;
-            case r: h = (g - b) / d + (g < b ? 6 : 0); break;
-            case g: h = (b - r) / d + 2; break;
-            case b: h = (r - g) / d + 4; break;
-            default: h = 0; break;
+            case min:
+                h = 0;
+                break;
+            case r:
+                h = (g - b) / d + (g < b ? 6 : 0);
+                break;
+            case g:
+                h = (b - r) / d + 2;
+                break;
+            case b:
+                h = (r - g) / d + 4;
+                break;
+            default:
+                h = 0;
+                break;
         }
         h /= 6;
         return [h, s, v];
     };
 
-    
-
-    sort = (docs: {layout: Doc;  data: Doc; }[], sortType: string, isDesc: boolean) => {
-
+    sort = (docs: { layout: Doc; data: Doc }[], sortType: string, isDesc: boolean) => {
         docs.sort((docA, docB) => {
             let typeA;
-            let typeB             
+            let typeB;
 
-            switch(sortType) {
-                case "color":
+            switch (sortType) {
+                case 'color':
                     typeA = this.hexToHsv(StrCast(docA.layout.backgroundColor)) ?? ''; // If docA.type is undefined, use an empty string
                     typeB = this.hexToHsv(StrCast(docB.layout.backgroundColor)) ?? ''; // If docB.type is undefined, use an empty string
-                    break
+                    break;
 
-                case "custom":
-                    typeA = this.customGroupDictionary.get(docs.indexOf(docA)) ?? ''
+                case 'custom':
+                    typeA = this.customGroupDictionary.get(docs.indexOf(docA)) ?? '';
                     // console.log(typeA + "A")
-                    typeB = this.customGroupDictionary.get(docs.indexOf(docB)) ?? ''
+                    typeB = this.customGroupDictionary.get(docs.indexOf(docB)) ?? '';
                     // console.log(typeB + 'b')
-                    break
-
+                    break;
 
                 default:
                     typeA = docA.layout.type ?? ''; // If docA.type is undefined, use an empty string
                     typeB = docB.layout.type ?? ''; // If docB.type is undefined, use an empty string
-                    break
+                    break;
             }
-            
 
             // Perform a basic string comparison if types are strings
             let out = 0;
@@ -284,19 +271,15 @@ export class CollectionCardView extends CollectionSubView() {
             if (typeA > typeB) out = 1;
             if (isDesc) out *= -1; // Reverse the sort order if descending is true
             return out;
-            });
-
-        return {docs}
-    }
+        });
 
-    
+        return { docs };
+    };
 
     // @computed get cards(){
 
-
     // }
 
-    
     displayDoc = (childPair: { layout: Doc; data: Doc }, screenToLocalTransform: () => Transform) => {
         return (
             <DocumentView
@@ -322,81 +305,76 @@ export class CollectionCardView extends CollectionSubView() {
             />
         );
     };
-   
 
     @observable docRefs = new ObservableMap<Doc, DocumentView>();
 
     @observable maxRowCount = 10;
 
     overflowAmCardsCalc(index: number) {
-        if (this.inactiveDocs().length < this.maxRowCount){
-            return this.inactiveDocs().length
+        if (this.inactiveDocs().length < this.maxRowCount) {
+            return this.inactiveDocs().length;
         }
-        // 13 - 3 = 10 
-        const totalCards = this.inactiveDocs().length
+        // 13 - 3 = 10
+        const totalCards = this.inactiveDocs().length;
         // if 9 or less
-        if ( index < ((totalCards - (totalCards % 10)))){
-            return this.maxRowCount
+        if (index < totalCards - (totalCards % 10)) {
+            return this.maxRowCount;
         }
         //(3)
-        return totalCards % 10
-
+        return totalCards % 10;
     }
 
     overflowIndexCalc(realIndex: number) {
-        if (realIndex < 10){
-            return realIndex
+        if (realIndex < 10) {
+            return realIndex;
         }
 
-        return realIndex % 10
-
+        return realIndex % 10;
     }
 
-    translateOverflowX(realIndex: number, calcRowCards: number){
-        if (realIndex < this.maxRowCount){
-            return 0
+    translateOverflowX(realIndex: number, calcRowCards: number) {
+        if (realIndex < this.maxRowCount) {
+            return 0;
         }
 
-        return (10 - calcRowCards) * (this.panelWidth()/2)
+        return (10 - calcRowCards) * (this.panelWidth() / 2);
     }
 
-   
     calculateTranslateY(isHovered: boolean, isSelected: boolean, realIndex: number, amCards: number, calcRowIndex: number) {
-
         let trans = 0;
         if (isHovered) {
             trans += this.translateHover(realIndex);
         }
-        
+
         trans += this.translateY(amCards, calcRowIndex, realIndex);
-        
 
         if (isSelected) {
             trans = 50 * this.fitContentScale;
         }
 
-        return trans
+        return trans;
     }
 
+    @observable _forceChildXf = false;
     @computed get contentSorted() {
-        const sortedDocs = this.sortedDocsType.docs; 
-        // const amCards = this.inactiveDocs().length; 
+        const sortedDocs = this.sortedDocsType.docs;
+        // const amCards = this.inactiveDocs().length;
 
         // Map sorted documents to their rendered components
         return sortedDocs.map((childPair, index) => {
-            // const childPair = { layout: doc, data: doc }; 
-
+            // const childPair = { layout: doc, data: doc };
 
             const isHovered = this.hoveredNodeIndex === index;
-            const childPairIndex = this.myChildLayoutPairs.indexOf(childPair)
+            const childPairIndex = this.myChildLayoutPairs.indexOf(childPair);
             const realIndex = this.sortedDocsType.docs.filter(d => !SelectionManager.IsSelected(d.layout)).indexOf(childPair);
-            const calcRowIndex = this.overflowIndexCalc(realIndex)
+            const calcRowIndex = this.overflowIndexCalc(realIndex);
 
-            const amCards = this.overflowAmCardsCalc(realIndex)
+            const amCards = this.overflowAmCardsCalc(realIndex);
 
             const isSelected = SelectionManager.IsSelected(childPair.layout);
 
             const childScreenToLocal = () => {
+                this._forceChildXf;
                 const dref = this.docRefs.get(childPair.layout);
                 const { translateX, translateY, scale } = Utils.GetScreenTransform(dref?.ContentDiv);
                 return new Transform(-translateX + (dref?.centeringX || 0) * scale, -translateY + (dref?.centeringY || 0) * scale, 1).scale(1 / scale).rotate(!isSelected ? -this.rotate(amCards, calcRowIndex) : 0);
@@ -406,6 +384,16 @@ export class CollectionCardView extends CollectionSubView() {
                 <div
                     key={childPair.layout[Id]}
                     className={`card-item${isSelected ? '-active' : ''}`}
+                    onPointerUp={e => {
+                        SnappingManager.SetIsResizing(this.Document);
+                        setTimeout(
+                            action(() => {
+                                SnappingManager.SetIsResizing(undefined);
+                                this._forceChildXf = !this._forceChildXf;
+                            }),
+                            400
+                        );
+                    }}
                     style={{
                         width: this.panelWidth(),
                         height: this.panelHeight(childPair.layout)(),
@@ -416,69 +404,47 @@ export class CollectionCardView extends CollectionSubView() {
                             scale(${isSelected ? 1.25 : 1})
                         `,
                     }}
-                    onMouseEnter={() => this.setHoveredNodeIndex(index)}
-                    
-                    >
+                    onMouseEnter={() => this.setHoveredNodeIndex(index)}>
                     {this.displayDoc(childPair, childScreenToLocal)}
 
                     {this._props.Document.cardSort == 'custom' ? this.renderButtons(childPairIndex) : ''}
-
                 </div>
             );
         });
     }
 
-    @observable amGroups = 0
-    @observable customGroupDictionary = new Map<
-       number, number>();
-
+    @observable amGroups = 0;
+    @observable customGroupDictionary = new Map<number, number>();
 
     @action toggleButton(childPairIndex: number, buttonID: number) {
-    
         this.customGroupDictionary.set(childPairIndex, buttonID);
     }
 
-    renderButtons (childPairIndex: number) {
+    renderButtons(childPairIndex: number) {
         const buttons = []; // Array to hold the button elements
 
-        let amButtons = 4
+        let amButtons = 4;
 
-        if (this.amGroups > 4){
-            amButtons = this.amGroups
+        if (this.amGroups > 4) {
+            amButtons = this.amGroups;
         }
 
-        let activeButtonIndex = this.customGroupDictionary.get(childPairIndex)
+        let activeButtonIndex = this.customGroupDictionary.get(childPairIndex);
 
         for (let i = 0; i < amButtons; i++) {
-            const isActive = activeButtonIndex == i
-      
-            buttons.push(
-                <button key={i}
-                    style = {{backgroundColor: `${isActive ?  "#4476f7" : "#323232"}`}}
-                    onClick={() => this.toggleButton(childPairIndex, i)} >
-                </button>); 
+            const isActive = activeButtonIndex == i;
+
+            buttons.push(<button key={i} style={{ backgroundColor: `${isActive ? '#4476f7' : '#323232'}` }} onClick={() => this.toggleButton(childPairIndex, i)}></button>);
         }
 
-        const totalWidth = amButtons * 35 + (amButtons * 2* 5) + 6;
+        const totalWidth = amButtons * 35 + amButtons * 2 * 5 + 6;
         return (
             <div className="card-button-container" style={{ width: `${totalWidth}px` }}>
                 {buttons}
             </div>
-        );  
+        );
     }
 
-
-    
-
-
-
-
-
-
-
-
-    
-
     // @computed get content() {
     //     // const currentIndex = NumCast(this.layoutDoc._carousel_index);
     //     const amCards = this.inactiveDocs().length;
@@ -486,7 +452,6 @@ export class CollectionCardView extends CollectionSubView() {
     //     // const sortedDocs = this.sortedDocsType.docs; // Retrieve sorted documents
 
     //     // const myInactives =
-        
 
     //     return this.myChildLayoutPairs.map((childPair, index) => {
     //         const isSelected = this.isSelected(index);
@@ -511,11 +476,11 @@ export class CollectionCardView extends CollectionSubView() {
     //                     width: this.panelWidth(),
     //                     height: this.panelHeight(childPair.layout)(),
     //                     transform: `
-    //                         rotate(${!isSelected ? this.rotate(amCards, inactiveIndex) : 0}deg) 
+    //                         rotate(${!isSelected ? this.rotate(amCards, inactiveIndex) : 0}deg)
     //                         translateY(${isHovered ? this.translateHover(index) : isSelected ? 50 * this.fitContentScale : this.translateY(amCards, inactiveIndex)}px)
     //                         translateX(${isSelected ? (this._props.PanelWidth() / 2) * this.fitContentScale - this.childDocumentWidth : 0}px)
     //                         scale(${isSelected ? 1.25 : 1})
-                            
+
     //                         `, //scale has to be applied last or selected offset gets messed up
     //                 }}
     //                 // onClick={() => this.setSelectedNodeIndex(index)}
@@ -530,23 +495,20 @@ export class CollectionCardView extends CollectionSubView() {
     // }
 
     @computed get translateWrapperX() {
-
-        let translate = 0
+        let translate = 0;
 
         if (this.inactiveDocs().length != this.myChildLayoutPairs.length && this.inactiveDocs().length < 10) {
             translate += this.panelWidth() / 2;
         }
 
-        console.log("in" + this.inactiveDocs().length)
-        console.log("max" + this.maxRowCount)
+        console.log('in' + this.inactiveDocs().length);
+        console.log('max' + this.maxRowCount);
 
         // if (this.inactiveDocs().length > this.maxRowCount){
         //     translate += ((this.inactiveDocs().length % this.maxRowCount) * this.panelWidth()) / 2
         //     console.log("trans" + (this.inactiveDocs().length % this.maxRowCount) / 2 )
         // }
 
-
-
         return translate;
     }
 
@@ -560,8 +522,6 @@ export class CollectionCardView extends CollectionSubView() {
     //     }
     // }
 
-    
-
     render() {
         return (
             <div
@@ -598,4 +558,4 @@ export class CollectionCardView extends CollectionSubView() {
             </div>
         );
     }
-}
\ No newline at end of file
+}
-- 
cgit v1.2.3-70-g09d2

