add inertial scrolling.

Hunter
Tuesday, April 1st, 2025 at 12:03 AM

index.html+77 

index.html
 261  			}
 262  		});
 263  		document.addEventListener('DOMContentLoaded', function() {
 264 +				// Variables for scroll handling
 265 +				let lastScrollPosition = 0;
 266 +				let isScrolling = false;
 267 +				let scrollDebounceTimer;
 268  			const appContainer = document.getElementById('app-container');
 269  			let rootTask = loadTasksFromLocalStorage();
 270  			let currentTask = rootTask;

1097  
1098  			document.addEventListener('keydown', handleSave);
1099  			document.addEventListener('keydown', handleOpen);
1100 +			
1101 +			// Add scroll handling to navigate tasks with inertia
1102 +			window.addEventListener('wheel', handleScroll, { passive: false });
1103 +			
1104 +			// Scroll inertia implementation
1105 +			const scrollState = {
1106 +				momentum: 0,
1107 +				isAnimating: false,
1108 +				lastScrollTime: Date.now(),
1109 +				scrollAccumulator: 0,
1110 +				taskNavigationThreshold: 250  // Pixels needed to move one task
1111 +			};
1112 +			
1113 +			function handleScroll(e) {
1114 +				// Prevent the default scroll behavior
1115 +				e.preventDefault();
1116 +				
1117 +				// Get scroll delta and update time
1118 +				const now = Date.now();
1119 +				const timeDelta = now - scrollState.lastScrollTime;
1120 +				scrollState.lastScrollTime = now;
1121 +				
1122 +				// Calculate momentum (higher for faster scrolls)
1123 +				const rawDelta = e.deltaY || e.detail || -e.wheelDelta;
1124 +				const delta = Math.sign(rawDelta) * Math.min(Math.abs(rawDelta), 100);  // Cap delta
1125 +				
1126 +				// Add to momentum based on time between scrolls (faster scrolls = more momentum)
1127 +				if (timeDelta < 100) {
1128 +					// Rapid scrolling gets more momentum
1129 +					scrollState.momentum += delta * (1 + (100 - timeDelta) / 100);
1130 +				} else {
1131 +					// Slower scrolling gets normal momentum
1132 +					scrollState.momentum += delta;
1133 +				}
1134 +				
1135 +				// Start animation if not already running
1136 +				if (!scrollState.isAnimating) {
1137 +					scrollState.isAnimating = true;
1138 +					animateMomentumScroll();
1139 +				}
1140 +			}
1141 +			
1142 +			function animateMomentumScroll() {
1143 +				// If momentum is close to zero, stop animation
1144 +				if (Math.abs(scrollState.momentum) < 0.5) {
1145 +					scrollState.momentum = 0;
1146 +					scrollState.isAnimating = false;
1147 +					return;
1148 +				}
1149 +				
1150 +				// Add momentum to accumulator
1151 +				scrollState.scrollAccumulator += scrollState.momentum;
1152 +				
1153 +				// Check if we've crossed the threshold to move tasks
1154 +				if (Math.abs(scrollState.scrollAccumulator) >= scrollState.taskNavigationThreshold) {
1155 +					const tasksToMove = Math.floor(Math.abs(scrollState.scrollAccumulator) / scrollState.taskNavigationThreshold);
1156 +					const direction = scrollState.scrollAccumulator > 0 ? 'down' : 'up';
1157 +					
1158 +					// Move the specified number of tasks
1159 +					for (let i = 0; i < tasksToMove; i++) {
1160 +						navigateTasks(direction);
1161 +					}
1162 +					
1163 +					// Remove the used part from accumulator
1164 +					scrollState.scrollAccumulator = scrollState.scrollAccumulator % scrollState.taskNavigationThreshold;
1165 +				}
1166 +				
1167 +				// Apply friction to slow down momentum (adjust factor for feel)
1168 +				scrollState.momentum *= 0.6;
1169 +				
1170 +				// Continue animation
1171 +				requestAnimationFrame(animateMomentumScroll);
1172 +			}
1173  
1174  			getThemesFromCSS();
1175  			setInitialTheme();