From 235ce5716edc2f7cbe80fdccf26eac7269587839 Mon Sep 17 00:00:00 2001
From: Jake Vanderwerf <get@jakevanderwerf.ca>
Date: Mon, 08 Jun 2026 04:38:18 +0000
Subject: [PATCH] =FavouritesManager.php and FavouritesRoutes.php fixes. Moving all logic to FavouritesManager.php. Still some left to do

---
 assets/js/concise/Gallery.js |   80 +++++++++++++++++++++++-----------------
 1 files changed, 46 insertions(+), 34 deletions(-)

diff --git a/assets/js/concise/Gallery.js b/assets/js/concise/Gallery.js
index 4890b50..950aa71 100644
--- a/assets/js/concise/Gallery.js
+++ b/assets/js/concise/Gallery.js
@@ -26,7 +26,6 @@
 		this.initModal();
 		this.initListeners();
 		this.initSubscribers();
-
 	}
 	/*********************************************************************
 	 ELEMENTS
@@ -42,7 +41,8 @@
 				image: '.image',
 				leftImage: '.image-left',
 				rightImage: '.image-right',
-				counter: '.counter'
+				counter: '.counter',
+				caption: 'details .item-info'
 			},
 		}
 		this.ui = window.uiFromSelectors(this.elements);
@@ -66,6 +66,16 @@
 		let selector = filtered ? `[data-gallery="${filtered}"]` : this.elements.imageSelector;
 		this.items = Array.from(document.querySelectorAll(selector))
 			.map((img, index) => {
+				let caption = '';
+				if (Object.hasOwn(img.dataset, 'caption')) {
+					caption = img.parentElement.querySelector(img.dataset.caption).cloneNode(true);
+				} else {
+					caption = img.nextElementSibling && img.nextElementSibling.tagName === 'FIGCAPTION' ?
+						img.nextElementSibling.textContent :
+						'';
+				}
+
+
 				return {
 					id: img.dataset.id||index,
 					srcset: img.srcset || img.src, // Clone the srcset from page
@@ -73,7 +83,8 @@
 					src: img.currentSrc || img.src, // Fallback
 					full: img.dataset.full || img.src,
 					alt: img.alt || '',
-					element: img
+					element: img,
+					caption: caption
 				};
 			});
 	}
@@ -101,10 +112,8 @@
 			this.toggleGallery(true);
 		} else if (this.modal.isOpen) {
 			if (window.targetCheck(e, this.elements.gallery.nextButton)) {
-				console.log('Next');
 				this.nextElement();
 			} else if (window.targetCheck(e, this.elements.gallery.prevButton)) {
-				console.log('Previous');
 				this.prevElement();
 			}
 		}
@@ -193,17 +202,12 @@
 		// PINCH (two pointers)
 		if (this.activePointers.size === 2) {
 			const pts = [...this.activePointers.values()];
-			const dist = Math.hypot(
-				pts[0].x - pts[1].x,
-				pts[0].y - pts[1].y
-			);
+			const dist = Math.hypot(pts[0].x - pts[1].x, pts[0].y - pts[1].y);
+			const increment = this.pinchStartScale * (dist / this.pinchStartDist) - this.zoom.scale;
 
-			const newScale = this.pinchStartScale * (dist / this.pinchStartDist);
-			const increment = newScale - this.zoom.scale;
-
-			// Zoom centered (NO midpoint)
-			this.handleZoom(increment);
-
+			const midX = (pts[0].x + pts[1].x) / 2;  // ← anchor to finger midpoint
+			const midY = (pts[0].y + pts[1].y) / 2;
+			this.handleZoom(increment, midX, midY);
 			return;
 		}
 
@@ -216,35 +220,26 @@
 	}
 
 	onPointerUp(e) {
+		const last = this.activePointers.get(e.pointerId); // grab before delete
 		this.activePointers.delete(e.pointerId);
 
 		if (this.activePointers.size < 2) {
 			this.pinchStartDist = 0;
 		}
 
-		// Only check for swipe if we weren't panning and no more active pointers
-		if (!this.zoom.panning && this.activePointers.size === 0) {
-			// End of tap or swipe - detect swipe
-			this.swipe.endX = e.clientX;
-			this.swipe.endY = e.clientY;
-			const dx = this.swipe.endX - this.swipe.startX;
-			const dy = this.swipe.endY - this.swipe.startY;
+		if (this.zoom.scale <= 1 && !this.zoom.panning && this.activePointers.size === 0) {
+			const endX = last?.x ?? e.clientX; // use tracked position, fall back to event
+			const endY = last?.y ?? e.clientY;
+			const dx = endX - this.swipe.startX;
+			const dy = endY - this.swipe.startY;
 
-			if (Math.abs(dx) > this.zoom.threshold) {
-				if (dx > 0) {
-					console.log('Swipe right');
-					this.prevElement();
-				} else {
-					console.log('Swipe left');
-					this.nextElement();
-				}
+			if (Math.abs(dx) > this.zoom.threshold && Math.abs(dx) > Math.abs(dy)) {
+				dx > 0 ? this.prevElement() : this.nextElement();
 			}
 		}
 
-		// Reset panning state when all pointers are released
 		if (this.activePointers.size === 0) {
 			this.zoom.panning = false;
-			// Reset cursor based on zoom state
 			this.ui.gallery.image.style.cursor = this.zoom.scale > 1 ? 'grab' : 'default';
 		}
 	}
@@ -290,12 +285,19 @@
 	}
 
 	applyTransform() {
-		// this.clampPan();
+		this.clampPan();
 		const img = this.ui.gallery.image;
 		img.style.transform = `translate(${this.zoom.x}px, ${this.zoom.y}px) scale(${this.zoom.scale})`;
 		// Update cursor based on zoom level
 		img.style.cursor = this.zoom.scale > 1 ? 'grab' : 'default';
 	}
+	clampPan() {
+		const img = this.ui.gallery.image;
+		const excessX = Math.max(0, (img.offsetWidth  * this.zoom.scale - window.innerWidth)  / 2);
+		const excessY = Math.max(0, (img.offsetHeight * this.zoom.scale - window.innerHeight) / 2);
+		this.zoom.x = Math.max(-excessX, Math.min(excessX, this.zoom.x));
+		this.zoom.y = Math.max(-excessY, Math.min(excessY, this.zoom.y));
+	}
 	resetZoom() {
 		this.zoom.scale = 1;
 		this.zoom.x = 0;
@@ -394,7 +396,17 @@
 		galleryImg.src = item.src; // Fallback
 		galleryImg.alt = item.alt;
 
-		// ALWAYS load full resolution for zoom quality
+		window.removeChildren(this.ui.gallery.caption);
+		if (typeof item.caption === 'object') {
+			this.ui.gallery.caption.append(item.caption);
+
+		} else {
+			this.ui.gallery.caption.textContent = item.caption;
+		}
+
+
+
+
 		if (item.full && item.full !== item.src) {
 			const fullImg = new Image();
 			fullImg.onload = () => {

--
Gitblit v1.10.0