Improve day swipe and sleep handling
This commit is contained in:
+69
-12
@@ -1223,7 +1223,7 @@
|
||||
valueInput.placeholder = config.placeholder;
|
||||
valueInput.required = !!config.showValue;
|
||||
valueInput.value = config.showValue ? valueInput.value : "";
|
||||
valueInput.step = type === "sleep" ? "0.25" : "1";
|
||||
valueInput.step = type === "sleep" ? "0.01" : "1";
|
||||
}
|
||||
if (unitInput) {
|
||||
unitInput.value = config.unit;
|
||||
@@ -1454,11 +1454,61 @@
|
||||
let dragging = false;
|
||||
let didSwipe = false;
|
||||
let activePointerId = null;
|
||||
let currentOffset = 0;
|
||||
let targetOffset = 0;
|
||||
let animationFrame = null;
|
||||
const prefetchedDays = new Set();
|
||||
|
||||
const setSlideProgress = offset => {
|
||||
const progress = Math.min(1, Math.abs(offset) / 120);
|
||||
daySlider.style.setProperty("--day-slider-offset", `${offset.toFixed(1)}px`);
|
||||
daySlider.style.setProperty("--day-slider-scale", (1 - (progress * 0.025)).toFixed(3));
|
||||
swipeContainer.style.setProperty("--day-prev-hint", offset > 0 ? progress.toFixed(3) : "0");
|
||||
swipeContainer.style.setProperty("--day-next-hint", offset < 0 ? progress.toFixed(3) : "0");
|
||||
};
|
||||
|
||||
const animateSlide = () => {
|
||||
currentOffset += (targetOffset - currentOffset) * 0.34;
|
||||
if (Math.abs(targetOffset - currentOffset) < 0.4) {
|
||||
currentOffset = targetOffset;
|
||||
}
|
||||
|
||||
setSlideProgress(currentOffset);
|
||||
|
||||
if (currentOffset !== targetOffset) {
|
||||
animationFrame = window.requestAnimationFrame(animateSlide);
|
||||
} else {
|
||||
animationFrame = null;
|
||||
}
|
||||
};
|
||||
|
||||
const setTargetOffset = offset => {
|
||||
targetOffset = offset;
|
||||
if (animationFrame === null) {
|
||||
animationFrame = window.requestAnimationFrame(animateSlide);
|
||||
}
|
||||
};
|
||||
|
||||
const preloadDay = date => {
|
||||
if (!date || prefetchedDays.has(date)) {
|
||||
return;
|
||||
}
|
||||
|
||||
prefetchedDays.add(date);
|
||||
window.fetch(dashboardDayPath(date), {
|
||||
credentials: "same-origin",
|
||||
cache: "force-cache",
|
||||
priority: "low"
|
||||
}).catch(() => {});
|
||||
};
|
||||
|
||||
preloadDay(swipeContainer.dataset.prevDate);
|
||||
preloadDay(swipeContainer.dataset.nextDate);
|
||||
|
||||
const resetStrip = () => {
|
||||
dayStrip.classList.remove("is-dragging");
|
||||
daySlider.classList.remove("is-dragging");
|
||||
daySlider.style.setProperty("--day-slider-offset", "0px");
|
||||
setTargetOffset(0);
|
||||
};
|
||||
|
||||
const handleSwipe = (deltaX, deltaY) => {
|
||||
@@ -1469,18 +1519,18 @@
|
||||
|
||||
if (deltaX < 0 && swipeContainer.dataset.nextDate) {
|
||||
didSwipe = true;
|
||||
daySlider.style.setProperty("--day-slider-offset", "-120%");
|
||||
setSlideProgress(-window.innerWidth);
|
||||
window.location.href = dashboardDayPath(swipeContainer.dataset.nextDate);
|
||||
} else if (deltaX > 0 && swipeContainer.dataset.prevDate) {
|
||||
didSwipe = true;
|
||||
daySlider.style.setProperty("--day-slider-offset", "120%");
|
||||
setSlideProgress(window.innerWidth);
|
||||
window.location.href = dashboardDayPath(swipeContainer.dataset.prevDate);
|
||||
} else {
|
||||
resetStrip();
|
||||
}
|
||||
};
|
||||
|
||||
dayStrip.addEventListener("pointerdown", event => {
|
||||
daySlider.addEventListener("pointerdown", event => {
|
||||
if (event.target.closest("input, textarea, select, label, [data-stepper], .dashboard-overlay")) {
|
||||
dragging = false;
|
||||
return;
|
||||
@@ -1493,10 +1543,10 @@
|
||||
pointerStartY = event.clientY;
|
||||
dayStrip.classList.add("is-dragging");
|
||||
daySlider.classList.add("is-dragging");
|
||||
dayStrip.setPointerCapture?.(event.pointerId);
|
||||
daySlider.setPointerCapture?.(event.pointerId);
|
||||
});
|
||||
|
||||
dayStrip.addEventListener("pointermove", event => {
|
||||
daySlider.addEventListener("pointermove", event => {
|
||||
if (!dragging || (activePointerId !== null && event.pointerId !== activePointerId)) {
|
||||
return;
|
||||
}
|
||||
@@ -1510,10 +1560,17 @@
|
||||
return;
|
||||
}
|
||||
|
||||
daySlider.style.setProperty("--day-slider-offset", `${Math.max(-120, Math.min(120, deltaX))}px`);
|
||||
const dampedOffset = Math.sign(deltaX) * Math.min(148, Math.pow(Math.abs(deltaX), 0.88) * 1.6);
|
||||
setTargetOffset(dampedOffset);
|
||||
|
||||
if (deltaX < -32) {
|
||||
preloadDay(swipeContainer.dataset.nextDate);
|
||||
} else if (deltaX > 32) {
|
||||
preloadDay(swipeContainer.dataset.prevDate);
|
||||
}
|
||||
});
|
||||
|
||||
dayStrip.addEventListener("pointerup", event => {
|
||||
daySlider.addEventListener("pointerup", event => {
|
||||
if (!dragging) {
|
||||
return;
|
||||
}
|
||||
@@ -1523,13 +1580,13 @@
|
||||
handleSwipe(event.clientX - pointerStartX, event.clientY - pointerStartY);
|
||||
});
|
||||
|
||||
dayStrip.addEventListener("pointercancel", () => {
|
||||
daySlider.addEventListener("pointercancel", () => {
|
||||
dragging = false;
|
||||
activePointerId = null;
|
||||
resetStrip();
|
||||
});
|
||||
|
||||
dayStrip.addEventListener("lostpointercapture", () => {
|
||||
daySlider.addEventListener("lostpointercapture", () => {
|
||||
if (!dragging) {
|
||||
return;
|
||||
}
|
||||
@@ -1539,7 +1596,7 @@
|
||||
resetStrip();
|
||||
});
|
||||
|
||||
dayStrip.addEventListener("click", event => {
|
||||
daySlider.addEventListener("click", event => {
|
||||
if (!didSwipe) {
|
||||
return;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user