consolidate duplicate code

Hunter
Wednesday, March 4th, 2026 at 3:23 PM

index.html+20-118

index.html
 892  					navigateTasks('down');
 893  				} else if (e.key === 'ArrowLeft' && (e.metaKey || e.ctrlKey) && e.shiftKey) {
 894  					e.preventDefault();
     -					pullSubtaskOutLayerAndNavigate(task);
 895 +					pullSubtaskOutLayer(task, true);
 896  				} else if (e.key === 'ArrowUp' && (e.metaKey || e.ctrlKey) && e.shiftKey) {
 897  					e.preventDefault();
     -					pushSubtaskIntoTargetAndNavigate(task, 'up');
 898 +					pushSubtaskIntoTarget(task, 'up', true);
 899  				} else if (e.key === 'ArrowDown' && (e.metaKey || e.ctrlKey) && e.shiftKey) {
 900  					e.preventDefault();
     -					pushSubtaskIntoTargetAndNavigate(task, 'down');
 901 +					pushSubtaskIntoTarget(task, 'down', true);
 902  				} else if (e.key === 'ArrowUp' && e.shiftKey) {
 903  					e.preventDefault();
 904  					moveSubtask(task, 'up');

 946  				scheduleSave();
 947  			}
 948  
     -			function pushSubtaskIntoTarget(subtask, direction) {
 949 +			function pushSubtaskIntoTarget(subtask, direction, navigate = false) {
 950  				// Don't allow pushing the current parent task
 951  				if (subtask === currentTask) {
 952  					return;
 953  				}
 954  
     -				const parentTask = findParentTask(subtask);
     -				if (!parentTask) return;
     -
     -				const index = parentTask.subtasks.findIndex(t => t.id === subtask.id);
     -				if (index === -1) return;
     -
     -				let targetTask = null;
     -				if (direction === 'up' && index > 0) {
     -					targetTask = parentTask.subtasks[index - 1];
     -				} else if (direction === 'down' && index < parentTask.subtasks.length - 1) {
     -					targetTask = parentTask.subtasks[index + 1];
     -				}
     -
     -				if (!targetTask) return;
     -
     -				// Remove the subtask from its current parent
     -				parentTask.subtasks.splice(index, 1);
     -
     -				// Add the subtask to the target task's subtasks
     -				targetTask.subtasks.push(subtask);
     -
     -				// Adjust moved task's state for its new parent
     -				adjustMovedTaskState(subtask, targetTask);
     -
     -				// Update parent task state after removal
     -				updateTaskAndAncestors(parentTask);
     -
     -				// Update target task state after addition
     -				updateTaskAndAncestors(targetTask);
     -
     -				// Re-render the view
     -				renderCurrentView();
     -
     -				// Focus on the target task that now contains the moved subtask
     -				selectAndFocusTask(targetTask);
     -
     -				scheduleSave();
     -			}
     -
     -			function pushSubtaskIntoTargetAndNavigate(subtask, direction) {
     -				// Don't allow pushing the current parent task
     -				if (subtask === currentTask) {
     -					return;
 955 +				if (navigate) {
 956 +					document.documentElement.style.scrollBehavior = 'auto';
 957  				}
 958  
     -				// Temporarily disable smooth scrolling
     -				document.documentElement.style.scrollBehavior = 'auto';
     -
 959  				const parentTask = findParentTask(subtask);
 960  				if (!parentTask) return;
 961  

 986  				// Update target task state after addition
 987  				updateTaskAndAncestors(targetTask);
 988  
     -				// Navigate into the target task and select the moved subtask
     -				navigateIntoTaskAndSelectSubtask(targetTask, subtask);
 989 +				if (navigate) {
 990 +					navigateIntoTaskAndSelectSubtask(targetTask, subtask);
 991 +				} else {
 992 +					renderCurrentView();
 993 +					selectAndFocusTask(targetTask);
 994 +				}
 995  
 996  				scheduleSave();
 997  			}
 998  
     -			function pullSubtaskOutLayer(subtask) {
 999 +			function pullSubtaskOutLayer(subtask, navigate = false) {
1000  				// Don't allow pulling the current parent task
1001  				if (subtask === currentTask) {
1002  					return;

1007  					return;
1008  				}
1009  
1010 +				if (navigate) {
1011 +					document.documentElement.style.scrollBehavior = 'auto';
1012 +				}
1013 +
1014  				const currentParent = findParentTask(subtask);
1015  				if (!currentParent) return;
1016  
1017  				// Find the grandparent (the outer layer we're pulling into)
     -				const grandParent = findGrandParentTask(currentParent);
1018 +				const grandParent = findParentTask(currentParent);
1019  				if (!grandParent) return;
1020  
1021  				// Remove the subtask from its current parent

1040  				updateTaskAndAncestors(currentParent);
1041  				updateTaskAndAncestors(grandParent);
1042  
     -				// Handle view and selection based on remaining tasks at current level
     -				if (currentParent.subtasks.length === 0 && taskPath.length > 1) {
     -					// No remaining subtasks, navigate to parent level and select the moved task
1043 +				if (navigate || (currentParent.subtasks.length === 0 && taskPath.length > 1)) {
1044 +					// Navigate to parent level and select the moved task
1045  					navigateToParentTaskAndSelectTask(subtask);
1046  				} else {
1047  					// Stay at current level and select adjacent task
1048  					renderCurrentView();
1049  					if (currentParent.subtasks.length > 0) {
     -						// Select the task that was above the moved one, or below if at the top
1050  						const targetIndex = Math.max(0, currentIndex - 1);
1051  						selectAndFocusTask(currentParent.subtasks[targetIndex]);
1052  					} else {
     -						// Focus on the parent task if no subtasks remain
1053  						selectAndFocusTask(currentParent);
1054  					}
1055  				}

1057  				scheduleSave();
1058  			}
1059  
     -			function pullSubtaskOutLayerAndNavigate(subtask) {
     -				// Don't allow pulling the current parent task
     -				if (subtask === currentTask) {
     -					return;
     -				}
     -
     -				// Don't allow pulling when at root level
     -				if (taskPath.length <= 1) {
     -					return;
     -				}
     -
     -				// Temporarily disable smooth scrolling
     -				document.documentElement.style.scrollBehavior = 'auto';
     -
     -				const currentParent = findParentTask(subtask);
     -				if (!currentParent) return;
     -
     -				// Find the grandparent (the outer layer we're pulling into)
     -				const grandParent = findGrandParentTask(currentParent);
     -				if (!grandParent) return;
     -
     -				// Remove the subtask from its current parent
     -				const currentIndex = currentParent.subtasks.findIndex(t => t.id === subtask.id);
     -				if (currentIndex === -1) return;
     -				currentParent.subtasks.splice(currentIndex, 1);
     -
     -				// Find where to insert in the grandparent's subtasks
     -				const currentParentIndex = grandParent.subtasks.findIndex(t => t.id === currentParent.id);
     -				if (currentParentIndex === -1) {
     -					// Fallback: add to end of grandparent's subtasks
     -					grandParent.subtasks.push(subtask);
     -				} else {
     -					// Insert after the current parent's position
     -					grandParent.subtasks.splice(currentParentIndex + 1, 0, subtask);
     -				}
     -
     -				// Adjust moved task's state for its new parent
     -				adjustMovedTaskState(subtask, grandParent);
     -
     -				// Update task states
     -				updateTaskAndAncestors(currentParent);
     -				updateTaskAndAncestors(grandParent);
     -
     -				// Always navigate to parent level and select the moved task
     -				navigateToParentTaskAndSelectTask(subtask);
     -
     -				scheduleSave();
     -			}
     -
     -			function findGrandParentTask(parentTask) {
     -				// Find the grandparent of the given parent task
     -				for (let i = taskPath.length - 1; i >= 0; i--) {
     -					const potentialGrandParent = taskPath[i];
     -					if (potentialGrandParent.subtasks.some(t => t.id === parentTask.id)) {
     -						return potentialGrandParent;
     -					}
     -				}
     -				return null;
     -			}
1060  
1061  			function addNewSubtask(parentTask, currentSubtask = null) {
1062  				const newSubtask = { id: Date.now(), text: '', state: 0, subtasks: [], selectedSubtaskId: null };