first pass at cmd+shift+left to pull subtask out
Hunter
Friday, June 27th, 2025 at 12:19 AM
894 applyShakeAnimation(task.id);
895 }
896 }
897 + } else if (e.key === 'ArrowLeft' && e.shiftKey && (e.metaKey || e.ctrlKey)) {
898 + e.preventDefault();
899 + pullSubtaskOutLayer(task);
900 } else if (e.key === 'ArrowLeft' && e.shiftKey) {
901 e.preventDefault();
902 if (!keyHandler.shiftLeft.pressed) {
966 scheduleSave();
967 }
968
969 + function pullSubtaskOutLayer(subtask) {
970 + // Don't allow pulling the current parent task
971 + if (subtask === currentTask) {
972 + return;
973 + }
974 +
975 + // Don't allow pulling when at root level
976 + if (taskPath.length <= 1) {
977 + return;
978 + }
979 +
980 + const currentParent = findParentTask(subtask);
981 + if (!currentParent) return;
982 +
983 + // Find the grandparent (the outer layer we're pulling into)
984 + const grandParent = findGrandParentTask(currentParent);
985 + if (!grandParent) return;
986 +
987 + // Remove the subtask from its current parent
988 + const currentIndex = currentParent.subtasks.findIndex(t => t.id === subtask.id);
989 + if (currentIndex === -1) return;
990 + currentParent.subtasks.splice(currentIndex, 1);
991 +
992 + // Find where to insert in the grandparent's subtasks
993 + const currentParentIndex = grandParent.subtasks.findIndex(t => t.id === currentParent.id);
994 + if (currentParentIndex === -1) {
995 + // Fallback: add to end of grandparent's subtasks
996 + grandParent.subtasks.push(subtask);
997 + } else {
998 + // Insert after the current parent's position
999 + grandParent.subtasks.splice(currentParentIndex + 1, 0, subtask);
1000 + }
1001 +
1002 + // Update task states
1003 + updateTaskAndAncestors(currentParent);
1004 + updateTaskAndAncestors(grandParent);
1005 +
1006 + // Navigate to the outer layer (grandparent level)
1007 + taskPath.pop(); // Remove current level
1008 + currentTask = taskPath[taskPath.length - 1]; // Set to grandparent
1009 +
1010 + // Re-render the view
1011 + renderCurrentView();
1012 +
1013 + // Focus on the moved subtask in its new location
1014 + selectAndFocusTask(subtask);
1015 +
1016 + scheduleSave();
1017 + }
1018 +
1019 + function findGrandParentTask(parentTask) {
1020 + // Find the grandparent of the given parent task
1021 + for (let i = taskPath.length - 1; i >= 0; i--) {
1022 + const potentialGrandParent = taskPath[i];
1023 + if (potentialGrandParent.subtasks.some(t => t.id === parentTask.id)) {
1024 + return potentialGrandParent;
1025 + }
1026 + }
1027 + return null;
1028 + }
1029 +
1030 function addNewSubtask(parentTask, currentSubtask = null) {
1031 const newSubtask = { id: Date.now(), text: '', state: 0, subtasks: [], selectedSubtaskId: null };
1032 if (currentSubtask) {