refined down arrow stopping

Hunter
Thursday, August 1st, 2024 at 1:03 AM

index.html+536-526

index.html
  1  <!DOCTYPE html>
  2  <html lang="en">
  3  <head>
    -    <meta charset="UTF-8">
    -    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    -    <link rel="icon" href="data:image/svg+xml,<svg xmlns=%22http://www.w3.org/2000/svg%22 viewBox=%220 0 100 100%22><text y=%22.9em%22 font-size=%2290%22>🪆</text></svg>">
    -    <title>todo</title>
    -    <style>
    -        body {
    -            font-family: Arial, sans-serif;
    -            max-width: 800px;
    -            margin: 0 auto;
    -            padding: 20px;
    -        }
    -        ul {
    -            list-style-type: none;
    -            padding-left: 20px;
    -        }
    -        input[type="text"] {
    -            border: none;
    -            background: transparent;
    -            font-size: 1.17em;
    -            font-weight: bold;
    -            width: calc(100% - 30px);
    -            margin-left: 5px;
    -            padding: 5px;
    -        }
    -        input[type="text"]:focus {
    -            outline: none;
    -        }
    -        .task-container {
    -            display: flex;
    -            align-items: center;
    -            margin: 5px 0;
    -        }
    -        .active {
    -            background-color: #e6f3ff;
    -        }
    -        .parent-task {
    -            font-size: 1.5em;
    -            font-weight: bold;
    -        }
    -        #breadcrumbs {
    -            font-size: 24px;
    -            margin-bottom: 10px;
    -        }
    -    </style>
    -    <script>
    -        document.addEventListener('DOMContentLoaded', function() {
    -            const appContainer = document.getElementById('app-container');
    -            let currentTask = { id: 'root', text: 'todo', state: 0, subtasks: [{ id: Date.now(), text: '', state: 0, subtasks: [] }], selectedSubtaskId: null };
    -            let taskPath = [currentTask];
    -
    -            const keyHandler = {
    -                backspace: {
    -                    canDelete: true,
    -                    blocked: false
    -                },
    -                enter: {
    -                    canAdd: true,
    -                    blocked: false
    -                },
    -                arrowDown: {
    -                    canAdd: true,
    -                    blocked: false
    -                }
    -            };
    -
    -            function createTaskElement(task, isParentTask = false) {
    -                const taskContainer = document.createElement('div');
    -                taskContainer.className = 'task-container';
    -                taskContainer.dataset.id = task.id;
    -                if (isParentTask) taskContainer.classList.add('parent-task');
    -
    -                const checkbox = document.createElement('input');
    -                checkbox.type = 'checkbox';
    -                updateCheckboxState(checkbox, task.state);
    -                checkbox.addEventListener('click', (e) => {
    -                    e.preventDefault();
    -                    toggleTaskState(task);
    -                });
    -
    -                const taskInput = document.createElement('input');
    -                taskInput.type = 'text';
    -                taskInput.value = task.text;
    -
    -                const keydownHandler = function(e) {
    -                    if (e.key === 'Backspace') {
    -                        if (keyHandler.backspace.blocked) {
    -                            e.preventDefault();
    -                            return;
    -                        }
    -                        if (taskInput.value === '' && keyHandler.backspace.canDelete) {
    -                            e.preventDefault();
    -                            if (task !== taskPath[0]) {
    -                                keyHandler.backspace.blocked = true;
    -                                if (task === currentTask) {
    -                                    deleteCurrentParentTask();
    -                                } else {
    -                                    deleteSubtask(task);
    -                                }
    -                            }
    -                        } else if (taskInput.value !== '') {
    -                            keyHandler.backspace.canDelete = false;
    -                        }
    -                    } else if (e.key === 'Enter' && !e.shiftKey) {
    -                        if (keyHandler.enter.blocked) {
    -                            e.preventDefault();
    -                            return;
    -                        }
    -                        if (keyHandler.enter.canAdd) {
    -                            e.preventDefault();
    -                            keyHandler.enter.blocked = true;
    -                            addNewSubtask(currentTask, task);
    -                        }
    -                    } else if (e.key === 'ArrowDown' && !e.shiftKey) {
    -                        if (keyHandler.arrowDown.blocked) {
    -                            e.preventDefault();
    -                            return;
    -                        }
    -                        if (keyHandler.arrowDown.canAdd && isLastSubtask(task)) {
    -                            e.preventDefault();
    -                            keyHandler.arrowDown.blocked = true;
    -                            addNewSubtask(currentTask, task);
    -                        } else {
    -                            handleKeyDown(e, task);
    -                        }
    -                    } else {
    -                        handleKeyDown(e, task);
    -                    }
    -                };
    -
    -                const keyupHandler = function(e) {
    -                    if (e.key === 'Backspace') {
    -                        keyHandler.backspace.canDelete = true;
    -                        keyHandler.backspace.blocked = false;
    -                    } else if (e.key === 'Enter') {
    -                        keyHandler.enter.canAdd = true;
    -                        keyHandler.enter.blocked = false;
    -                    } else if (e.key === 'ArrowDown') {
    -                        keyHandler.arrowDown.canAdd = true;
    -                        keyHandler.arrowDown.blocked = false;
    -                    }
    -                };
    -
    -                taskInput.addEventListener('keydown', keydownHandler);
    -                taskInput.addEventListener('keyup', keyupHandler);
    -                taskInput.addEventListener('keydown', copyActiveTaskText);
    -
    -                taskInput.addEventListener('input', () => {
    -                    task.text = taskInput.value;
    -                    if (task === currentTask) {
    -                        updatePageTitle(task);
    -                    }
    -                });
    -
    -                taskInput.addEventListener('focus', () => setActiveTask(taskInput, task));
    -
    -                taskContainer.appendChild(checkbox);
    -                taskContainer.appendChild(taskInput);
    -
    -                return taskContainer;
    -            }
    -
    -            function generateBreadcrumbs(rootTask, currentPath, selectedTaskId) {
    -                let breadcrumbs = '';
    -                let currentTask = rootTask;
    -                let currentDepth = 0;
    -
    -                for (let i = 0; i < currentPath.length - 1; i++) {
    -                    breadcrumbs += '○ ';
    -                    currentTask = currentTask.subtasks.find(t => t.id === currentPath[i + 1].id);
    -                }
    -
    -                breadcrumbs += '● ';
    -                currentDepth = currentPath.length - 1;
    -
    -                if (selectedTaskId !== currentTask.id) {
    -                    let selectedTask = currentTask.subtasks.find(t => t.id === selectedTaskId);
    -                    
    -                    if (selectedTask) {
    -                        function calculateMaxDepth(task, depth) {
    -                            if (task.subtasks.length === 0) return depth;
    -                            return Math.max(...task.subtasks.map(st => calculateMaxDepth(st, depth + 1)));
    -                        }
    -
    -                        let maxDepth = calculateMaxDepth(selectedTask, currentDepth + 1);
    -
    -                        for (let i = currentDepth + 1; i < maxDepth; i++) {
    -                            breadcrumbs += '○ ';
    -                        }
    -                    }
    -                }
    -
    -                return breadcrumbs.trim();
    -            }
    -
    -            function updateCheckboxState(checkbox, state) {
    -                checkbox.checked = state === 1;
    -                checkbox.indeterminate = state === 2;
    -            }
    -
    -            function toggleTaskState(task) {
    -                if (task.state === 1) {
    -                    if (task.subtasks.length === 0 || !task.subtasks.every(t => t.state === 1)) {
    -                        task.state = 0;
    -                        if (task.subtasks.length > 0) {
    -                            task.subtasks.forEach(subtask => {
    -                                if (subtask.state === 2) {
    -                                    subtask.state = 0;
    -                                }
    -                            });
    -                        }
    -                    }
    -                } else {
    -                    task.state = 1;
    -                    if (task.subtasks.length > 0) {
    -                        task.subtasks.forEach(subtask => {
    -                            if (subtask.state === 0) {
    -                                subtask.state = 2;
    -                            }
    -                        });
    -                    }
    -                }
    -                updateParentTaskState(task);
    -                renderCurrentView();
    -                selectAndFocusTask(task);
    -            }
    -
    -            function updateParentTaskState(task) {
    -                const parent = findParentTask(task);
    -                if (parent) {
    -                    const allChecked = parent.subtasks.every(t => t.state === 1);
    -                    const anyUnchecked = parent.subtasks.some(t => t.state === 0);
    -
    -                    if (allChecked) {
    -                        parent.state = 1;
    -                    } else if (anyUnchecked) {
    -                        parent.state = 0;
    -                    }
    -
    -                    updateParentTaskState(parent);
    -                }
    -            }
    -
    -            function updateSubtasksState(task, state) {
    -                task.subtasks.forEach(subtask => {
    -                    subtask.state = state;
    -                    if (subtask.subtasks.length > 0) {
    -                        updateSubtasksState(subtask, state);
    -                    }
    -                });
    -            }
    -
    -            function findParentTask(task) {
    -                for (let i = taskPath.length - 1; i >= 0; i--) {
    -                    const potentialParent = taskPath[i];
    -                    if (potentialParent.subtasks.some(t => t.id === task.id)) {
    -                        return potentialParent;
    -                    }
    -                }
    -                return null;
    -            }
    -
    -            function handleKeyDown(e, task) {
    -                if (e.key === 'Enter' && e.shiftKey) {
    -                    e.preventDefault();
    -                    toggleTaskState(task);
    -                } else if (e.key === 'ArrowUp' && !e.shiftKey) {
    -                    e.preventDefault();
    -                    navigateTasks('up');
    -                } else if (e.key === 'ArrowDown' && !e.shiftKey) {
    -                    e.preventDefault();
    -                    navigateTasks('down');
    -                } else if (e.key === 'ArrowUp' && e.shiftKey) {
    -                    e.preventDefault();
    -                    moveSubtask(task, 'up');
    -                } else if (e.key === 'ArrowDown' && e.shiftKey) {
    -                    e.preventDefault();
    -                    moveSubtask(task, 'down');
    -                } else if (e.key === 'ArrowRight' && e.shiftKey) {
    -                    e.preventDefault();
    -                    if (task !== currentTask) {
    -                        navigateIntoSubtask(task);
    -                    }
    -                } else if (e.key === 'ArrowLeft' && e.shiftKey) {
    -                    e.preventDefault();
    -                    navigateToParentTask();
    -                }
    -            }
    -
    -            function moveSubtask(subtask, direction) {
    -                const parentTask = findParentTask(subtask);
    -                if (!parentTask) return;
    -
    -                const index = parentTask.subtasks.findIndex(t => t.id === subtask.id);
    -                if (index === -1) return;
    -
    -                if (direction === 'up' && index > 0) {
    -                    [parentTask.subtasks[index - 1], parentTask.subtasks[index]] = [parentTask.subtasks[index], parentTask.subtasks[index - 1]];
    -                } else if (direction === 'down' && index < parentTask.subtasks.length - 1) {
    -                    [parentTask.subtasks[index], parentTask.subtasks[index + 1]] = [parentTask.subtasks[index + 1], parentTask.subtasks[index]];
    -                }
    -
    -                renderCurrentView();
    -                selectAndFocusTask(subtask);
    -            }
    -
    -            function addNewSubtask(parentTask, currentSubtask = null) {
    -                const newSubtask = { id: Date.now(), text: '', state: 0, subtasks: [], selectedSubtaskId: null };
    -                if (currentSubtask) {
    -                    const index = parentTask.subtasks.findIndex(t => t.id === currentSubtask.id);
    -                    parentTask.subtasks.splice(index + 1, 0, newSubtask);
    -                } else {
    -                    parentTask.subtasks.push(newSubtask);
    -                }
    -
    -                parentTask.state = 0;
    -                parentTask.subtasks.forEach(subtask => {
    -                    if (subtask.state === 2) {
    -                        subtask.state = 0;
    -                    }
    -                });
    -
    -                renderCurrentView();
    -                selectAndFocusTask(newSubtask);
    -            }
    -
    -            function selectAndFocusTask(task) {
    -                const taskInput = document.querySelector(`.task-container[data-id="${task.id}"] input[type="text"]`);
    -                if (taskInput) {
    -                    taskInput.focus();
    -                    setActiveTask(taskInput, task);
    -                }
    -            }
    -
    -            function deleteSubtask(subtask) {
    -                const parentTask = taskPath[taskPath.length - 1];
    -                const index = parentTask.subtasks.findIndex(t => t.id === subtask.id);
    -
    -                if (parentTask.id === 'root' && parentTask.subtasks.length === 1) {
    -                    return;
    -                }
    -
    -                parentTask.subtasks = parentTask.subtasks.filter(t => t.id !== subtask.id);
    -                updateParentTaskState(parentTask);
    -
    -                if (parentTask.subtasks.length === 0 && taskPath.length > 1) {
    -                    navigateToParentTask();
    -                } else {
    -                    renderCurrentView();
    -                    if (parentTask.subtasks.length > 0) {
    -                        const targetIndex = Math.max(0, index - 1);
    -                        selectAndFocusTask(parentTask.subtasks[targetIndex]);
    -                    } else {
    -                        selectAndFocusTask(parentTask);
    -                    }
    -                }
    -            }
    -
    -            function deleteCurrentParentTask() {
    -                if (taskPath.length <= 1) return; // Don't delete root task
    -
    -                const currentParentTask = taskPath[taskPath.length - 1];
    -                const grandparentTask = taskPath[taskPath.length - 2];
    -
    -                // Check if we're trying to delete the sole child of the root
    -                if (grandparentTask.id === 'root' && grandparentTask.subtasks.length === 1) {
    -                    return; // Don't allow deletion of the sole child of root
    -                }
    -
    -                const index = grandparentTask.subtasks.findIndex(t => t.id === currentParentTask.id);
    -
    -                grandparentTask.subtasks = grandparentTask.subtasks.filter(t => t.id !== currentParentTask.id);
    -                updateParentTaskState(grandparentTask);
    -
    -                taskPath.pop(); // Remove the deleted task from the path
    -                currentTask = grandparentTask;
    -
    -                if (grandparentTask.subtasks.length === 0 && taskPath.length > 1) {
    -                    // If we've just deleted the last subtask, navigate up another level
    -                    navigateToParentTask();
    -                } else {
    -                    renderCurrentView();
    -                    if (grandparentTask.subtasks.length > 0) {
    -                        // Select the subtask before the deleted one, or the one after if at the start
    -                        const targetIndex = Math.max(0, index - 1);
    -                        selectAndFocusTask(grandparentTask.subtasks[targetIndex]);
    -                    } else {
    -                        selectAndFocusTask(grandparentTask);
    -                    }
    -                }
    -            }
    -
    -            function navigateTasks(direction) {
    -                const tasks = currentTask.subtasks;
    -                const currentElement = document.activeElement;
    -                const currentContainer = currentElement.closest('.task-container');
    -                const currentIndex = Array.from(appContainer.querySelectorAll('.task-container')).indexOf(currentContainer);
    -
    -                if (direction === 'up') {
    -                    if (currentIndex > 0) {
    -                        const prevTask = currentIndex === 1 ? currentTask : tasks[currentIndex - 2];
    -                        selectAndFocusTask(prevTask);
    -                    }
    -                } else {
    -                    if (currentIndex < tasks.length) {
    -                        selectAndFocusTask(tasks[currentIndex]);
    -                    }
    -                }
    -            }
    -
    -            function navigateIntoSubtask(subtask) {
    -                if (subtask.subtasks.length > 0) {
    -                    currentTask.selectedSubtaskId = subtask.id;
    -                    taskPath.push(subtask);
  4 +	<meta charset="UTF-8">
  5 +	<meta name="viewport" content="width=device-width, initial-scale=1.0">
  6 +	<link rel="icon" href="data:image/svg+xml,<svg xmlns=%22http://www.w3.org/2000/svg%22 viewBox=%220 0 100 100%22><text y=%22.9em%22 font-size=%2290%22>🪆</text></svg>">
  7 +	<title>todo</title>
  8 +	<style>
  9 +		body {
 10 +			font-family: Arial, sans-serif;
 11 +			max-width: 800px;
 12 +			margin: 0 auto;
 13 +			padding: 20px;
 14 +		}
 15 +		ul {
 16 +			list-style-type: none;
 17 +			padding-left: 20px;
 18 +		}
 19 +		input[type="text"] {
 20 +			border: none;
 21 +			background: transparent;
 22 +			font-size: 1.17em;
 23 +			font-weight: bold;
 24 +			width: calc(100% - 30px);
 25 +			margin-left: 5px;
 26 +			padding: 5px;
 27 +		}
 28 +		input[type="text"]:focus {
 29 +			outline: none;
 30 +		}
 31 +		.task-container {
 32 +			display: flex;
 33 +			align-items: center;
 34 +			margin: 5px 0;
 35 +		}
 36 +		.active {
 37 +			background-color: #e6f3ff;
 38 +		}
 39 +		.parent-task {
 40 +			font-size: 1.5em;
 41 +			font-weight: bold;
 42 +		}
 43 +		#breadcrumbs {
 44 +			font-size: 24px;
 45 +			margin-bottom: 10px;
 46 +		}
 47 +	</style>
 48 +	<script>
 49 +		document.addEventListener('DOMContentLoaded', function() {
 50 +			const appContainer = document.getElementById('app-container');
 51 +			let currentTask = { id: 'root', text: 'todo', state: 0, subtasks: [{ id: Date.now(), text: '', state: 0, subtasks: [] }], selectedSubtaskId: null };
 52 +			let taskPath = [currentTask];
 53 +			let lastSubtaskDownArrowReleased = false;
 54 +
 55 +			const keyHandler = {
 56 +				backspace: {
 57 +					canDelete: true,
 58 +					blocked: false
 59 +				},
 60 +				enter: {
 61 +					canAdd: true,
 62 +					blocked: false
 63 +				},
 64 +				arrowDown: {
 65 +					canAdd: true,
 66 +					blocked: false
 67 +				}
 68 +			};
 69 +
 70 +			function createTaskElement(task, isParentTask = false) {
 71 +				const taskContainer = document.createElement('div');
 72 +				taskContainer.className = 'task-container';
 73 +				taskContainer.dataset.id = task.id;
 74 +				if (isParentTask) taskContainer.classList.add('parent-task');
 75 +
 76 +				const checkbox = document.createElement('input');
 77 +				checkbox.type = 'checkbox';
 78 +				updateCheckboxState(checkbox, task.state);
 79 +				checkbox.addEventListener('click', (e) => {
 80 +					e.preventDefault();
 81 +					toggleTaskState(task);
 82 +				});
 83 +
 84 +				const taskInput = document.createElement('input');
 85 +				taskInput.type = 'text';
 86 +				taskInput.value = task.text;
 87 +
 88 +				const keydownHandler = function(e) {
 89 +					if (e.key === 'Backspace') {
 90 +						if (keyHandler.backspace.blocked) {
 91 +							e.preventDefault();
 92 +							return;
 93 +						}
 94 +						if (taskInput.value === '' && keyHandler.backspace.canDelete) {
 95 +							e.preventDefault();
 96 +							if (task !== taskPath[0]) {
 97 +								keyHandler.backspace.blocked = true;
 98 +								if (task === currentTask) {
 99 +									deleteCurrentParentTask();
100 +								} else {
101 +									deleteSubtask(task);
102 +								}
103 +							}
104 +						} else if (taskInput.value !== '') {
105 +							keyHandler.backspace.canDelete = false;
106 +						}
107 +					} else if (e.key === 'Enter' && !e.shiftKey) {
108 +						if (keyHandler.enter.blocked) {
109 +							e.preventDefault();
110 +							return;
111 +						}
112 +						if (keyHandler.enter.canAdd) {
113 +							e.preventDefault();
114 +							keyHandler.enter.blocked = true;
115 +							addNewSubtask(currentTask, task);
116 +						}
117 +					} else if (e.key === 'ArrowDown' && !e.shiftKey) {
118 +						if (keyHandler.arrowDown.blocked) {
119 +							e.preventDefault();
120 +							return;
121 +						}
122 +						if (isLastSubtask(task) && (lastSubtaskDownArrowReleased || currentTask.subtasks.length === 1)) {
123 +							e.preventDefault();
124 +							keyHandler.arrowDown.blocked = true;
125 +							addNewSubtask(currentTask, task);
126 +							lastSubtaskDownArrowReleased = false;
127 +						} else {
128 +							handleKeyDown(e, task);
129 +						}
130 +					} else {
131 +						handleKeyDown(e, task);
132 +					}
133 +				};
134 +
135 +				const keyupHandler = function(e) {
136 +					if (e.key === 'Backspace') {
137 +						keyHandler.backspace.canDelete = true;
138 +						keyHandler.backspace.blocked = false;
139 +					} else if (e.key === 'Enter') {
140 +						keyHandler.enter.canAdd = true;
141 +						keyHandler.enter.blocked = false;
142 +					} else if (e.key === 'ArrowDown') {
143 +						keyHandler.arrowDown.canAdd = true;
144 +						keyHandler.arrowDown.blocked = false;
145 +						if (isLastSubtask(task)) {
146 +							lastSubtaskDownArrowReleased = true;
147 +						} else {
148 +							lastSubtaskDownArrowReleased = false;
149 +						}
150 +					}
151 +				};
152 +
153 +				taskInput.addEventListener('keydown', keydownHandler);
154 +				taskInput.addEventListener('keyup', keyupHandler);
155 +				taskInput.addEventListener('keydown', copyActiveTaskText);
156 +
157 +				taskInput.addEventListener('input', () => {
158 +					task.text = taskInput.value;
159 +					if (task === currentTask) {
160 +						updatePageTitle(task);
161 +					}
162 +				});
163 +
164 +				taskInput.addEventListener('focus', () => setActiveTask(taskInput, task));
165 +
166 +				taskContainer.appendChild(checkbox);
167 +				taskContainer.appendChild(taskInput);
168 +
169 +				return taskContainer;
170 +			}
171 +
172 +			function generateBreadcrumbs(rootTask, currentPath, selectedTaskId) {
173 +				let breadcrumbs = '';
174 +				let currentTask = rootTask;
175 +				let currentDepth = 0;
176 +
177 +				for (let i = 0; i < currentPath.length - 1; i++) {
178 +					breadcrumbs += '○ ';
179 +					currentTask = currentTask.subtasks.find(t => t.id === currentPath[i + 1].id);
180 +				}
181 +
182 +				breadcrumbs += '● ';
183 +				currentDepth = currentPath.length - 1;
184 +
185 +				if (selectedTaskId !== currentTask.id) {
186 +					let selectedTask = currentTask.subtasks.find(t => t.id === selectedTaskId);
187 +					
188 +					if (selectedTask) {
189 +						function calculateMaxDepth(task, depth) {
190 +							if (task.subtasks.length === 0) return depth;
191 +							return Math.max(...task.subtasks.map(st => calculateMaxDepth(st, depth + 1)));
192 +						}
193 +
194 +						let maxDepth = calculateMaxDepth(selectedTask, currentDepth + 1);
195 +
196 +						for (let i = currentDepth + 1; i < maxDepth; i++) {
197 +							breadcrumbs += '○ ';
198 +						}
199 +					}
200 +				}
201 +
202 +				return breadcrumbs.trim();
203 +			}
204 +
205 +			function updateCheckboxState(checkbox, state) {
206 +				checkbox.checked = state === 1;
207 +				checkbox.indeterminate = state === 2;
208 +			}
209 +
210 +			function toggleTaskState(task) {
211 +				if (task.state === 1) {
212 +					if (task.subtasks.length === 0 || !task.subtasks.every(t => t.state === 1)) {
213 +						task.state = 0;
214 +						if (task.subtasks.length > 0) {
215 +							task.subtasks.forEach(subtask => {
216 +								if (subtask.state === 2) {
217 +									subtask.state = 0;
218 +								}
219 +							});
220 +						}
221 +					}
222 +				} else {
223 +					task.state = 1;
224 +					if (task.subtasks.length > 0) {
225 +						task.subtasks.forEach(subtask => {
226 +							if (subtask.state === 0) {
227 +								subtask.state = 2;
228 +							}
229 +						});
230 +					}
231 +				}
232 +				updateParentTaskState(task);
233 +				renderCurrentView();
234 +				selectAndFocusTask(task);
235 +			}
236 +
237 +			function updateParentTaskState(task) {
238 +				const parent = findParentTask(task);
239 +				if (parent) {
240 +					const allChecked = parent.subtasks.every(t => t.state === 1);
241 +					const anyUnchecked = parent.subtasks.some(t => t.state === 0);
242 +
243 +					if (allChecked) {
244 +						parent.state = 1;
245 +					} else if (anyUnchecked) {
246 +						parent.state = 0;
247 +					}
248 +
249 +					updateParentTaskState(parent);
250 +				}
251 +			}
252 +
253 +			function updateSubtasksState(task, state) {
254 +				task.subtasks.forEach(subtask => {
255 +					subtask.state = state;
256 +					if (subtask.subtasks.length > 0) {
257 +						updateSubtasksState(subtask, state);
258 +					}
259 +				});
260 +			}
261 +
262 +			function findParentTask(task) {
263 +				for (let i = taskPath.length - 1; i >= 0; i--) {
264 +					const potentialParent = taskPath[i];
265 +					if (potentialParent.subtasks.some(t => t.id === task.id)) {
266 +						return potentialParent;
267 +					}
268 +				}
269 +				return null;
270 +			}
271 +
272 +			function handleKeyDown(e, task) {
273 +				if (e.key === 'Enter' && e.shiftKey) {
274 +					e.preventDefault();
275 +					toggleTaskState(task);
276 +				} else if (e.key === 'ArrowUp' && !e.shiftKey) {
277 +					e.preventDefault();
278 +					navigateTasks('up');
279 +				} else if (e.key === 'ArrowDown' && !e.shiftKey) {
280 +					e.preventDefault();
281 +					navigateTasks('down');
282 +				} else if (e.key === 'ArrowUp' && e.shiftKey) {
283 +					e.preventDefault();
284 +					moveSubtask(task, 'up');
285 +				} else if (e.key === 'ArrowDown' && e.shiftKey) {
286 +					e.preventDefault();
287 +					moveSubtask(task, 'down');
288 +				} else if (e.key === 'ArrowRight' && e.shiftKey) {
289 +					e.preventDefault();
290 +					if (task !== currentTask) {
291 +						navigateIntoSubtask(task);
292 +					}
293 +				} else if (e.key === 'ArrowLeft' && e.shiftKey) {
294 +					e.preventDefault();
295 +					navigateToParentTask();
296 +				}
297 +			}
298 +
299 +			function moveSubtask(subtask, direction) {
300 +				const parentTask = findParentTask(subtask);
301 +				if (!parentTask) return;
302 +
303 +				const index = parentTask.subtasks.findIndex(t => t.id === subtask.id);
304 +				if (index === -1) return;
305 +
306 +				if (direction === 'up' && index > 0) {
307 +					[parentTask.subtasks[index - 1], parentTask.subtasks[index]] = [parentTask.subtasks[index], parentTask.subtasks[index - 1]];
308 +				} else if (direction === 'down' && index < parentTask.subtasks.length - 1) {
309 +					[parentTask.subtasks[index], parentTask.subtasks[index + 1]] = [parentTask.subtasks[index + 1], parentTask.subtasks[index]];
310 +				}
311 +
312 +				renderCurrentView();
313 +				selectAndFocusTask(subtask);
314 +			}
315 +
316 +			function addNewSubtask(parentTask, currentSubtask = null) {
317 +				const newSubtask = { id: Date.now(), text: '', state: 0, subtasks: [], selectedSubtaskId: null };
318 +				if (currentSubtask) {
319 +					const index = parentTask.subtasks.findIndex(t => t.id === currentSubtask.id);
320 +					parentTask.subtasks.splice(index + 1, 0, newSubtask);
321 +				} else {
322 +					parentTask.subtasks.push(newSubtask);
323 +				}
324 +
325 +				parentTask.state = 0;
326 +				parentTask.subtasks.forEach(subtask => {
327 +					if (subtask.state === 2) {
328 +						subtask.state = 0;
329 +					}
330 +				});
331 +
332 +				renderCurrentView();
333 +				selectAndFocusTask(newSubtask);
334 +			}
335 +
336 +			function selectAndFocusTask(task) {
337 +				const taskInput = document.querySelector(`.task-container[data-id="${task.id}"] input[type="text"]`);
338 +				if (taskInput) {
339 +					taskInput.focus();
340 +					setActiveTask(taskInput, task);
341 +				}
342 +			}
343 +
344 +			function deleteSubtask(subtask) {
345 +				const parentTask = taskPath[taskPath.length - 1];
346 +				const index = parentTask.subtasks.findIndex(t => t.id === subtask.id);
347 +
348 +				if (parentTask.id === 'root' && parentTask.subtasks.length === 1) {
349 +					return;
350 +				}
351 +
352 +				parentTask.subtasks = parentTask.subtasks.filter(t => t.id !== subtask.id);
353 +				updateParentTaskState(parentTask);
354 +
355 +				if (parentTask.subtasks.length === 0 && taskPath.length > 1) {
356 +					navigateToParentTask();
357 +				} else {
358 +					renderCurrentView();
359 +					if (parentTask.subtasks.length > 0) {
360 +						const targetIndex = Math.max(0, index - 1);
361 +						selectAndFocusTask(parentTask.subtasks[targetIndex]);
362 +					} else {
363 +						selectAndFocusTask(parentTask);
364 +					}
365 +				}
366 +			}
367 +
368 +			function deleteCurrentParentTask() {
369 +				if (taskPath.length <= 1) return; // Don't delete root task
370 +
371 +				const currentParentTask = taskPath[taskPath.length - 1];
372 +				const grandparentTask = taskPath[taskPath.length - 2];
373 +
374 +				// Check if we're trying to delete the sole child of the root
375 +				if (grandparentTask.id === 'root' && grandparentTask.subtasks.length === 1) {
376 +					return; // Don't allow deletion of the sole child of root
377 +				}
378 +
379 +				const index = grandparentTask.subtasks.findIndex(t => t.id === currentParentTask.id);
380 +
381 +				grandparentTask.subtasks = grandparentTask.subtasks.filter(t => t.id !== currentParentTask.id);
382 +				updateParentTaskState(grandparentTask);
383 +
384 +				taskPath.pop(); // Remove the deleted task from the path
385 +				currentTask = grandparentTask;
386 +
387 +				if (grandparentTask.subtasks.length === 0 && taskPath.length > 1) {
388 +					// If we've just deleted the last subtask, navigate up another level
389 +					navigateToParentTask();
390 +				} else {
391 +					renderCurrentView();
392 +					if (grandparentTask.subtasks.length > 0) {
393 +						// Select the subtask before the deleted one, or the one after if at the start
394 +						const targetIndex = Math.max(0, index - 1);
395 +						selectAndFocusTask(grandparentTask.subtasks[targetIndex]);
396 +					} else {
397 +						selectAndFocusTask(grandparentTask);
398 +					}
399 +				}
400 +			}
401 +
402 +			function navigateTasks(direction) {
403 +				const tasks = currentTask.subtasks;
404 +				const currentElement = document.activeElement;
405 +				const currentContainer = currentElement.closest('.task-container');
406 +				const currentIndex = Array.from(appContainer.querySelectorAll('.task-container')).indexOf(currentContainer);
407 +
408 +				if (direction === 'up') {
409 +					if (currentIndex > 0) {
410 +						const prevTask = currentIndex === 1 ? currentTask : tasks[currentIndex - 2];
411 +						selectAndFocusTask(prevTask);
412 +					}
413 +					// } else if (currentTask !== taskPath[0]) {
414 +					// 	navigateToParentTask();
415 +					// }
416 +				} else {
417 +					if (currentIndex < tasks.length) {
418 +						selectAndFocusTask(tasks[currentIndex]);
419 +					}
420 +				}
421 +				lastSubtaskDownArrowReleased = false;
422 +			}
423 +
424 +			function navigateIntoSubtask(subtask) {
425 +				if (subtask.subtasks.length > 0) {
426 +					currentTask.selectedSubtaskId = subtask.id;
427 +					taskPath.push(subtask);
428  					currentTask = subtask;
    -                    updateBreadcrumbs(currentTask);
    -                    renderCurrentView();
    -                    const selectedSubtask = subtask.selectedSubtaskId ? 
    -                        subtask.subtasks.find(t => t.id === subtask.selectedSubtaskId) : 
    -                        subtask.subtasks[0];
    -                    selectAndFocusTask(selectedSubtask);
    -                } else {
    -                    addNewSubtask(subtask);
    -                    currentTask.selectedSubtaskId = subtask.id;
    -                    taskPath.push(subtask);
    -                    currentTask = subtask;
    -                    updateBreadcrumbs(currentTask);
    -                    renderCurrentView();
    -                    selectAndFocusTask(subtask.subtasks[0]);
    -                }
    -            }
    -
    -            function navigateToParentTask() {
    -                if (taskPath.length > 1) {
    -                    const currentTaskId = currentTask.id;
    -                    taskPath.pop();
    -                    currentTask = taskPath[taskPath.length - 1];
    -                    updateParentTaskState(currentTask);
    -                    updateBreadcrumbs(currentTask);
    -                    renderCurrentView();
    -                    const selectedSubtask = currentTask.subtasks.find(t => t.id === currentTaskId);
    -                    if (selectedSubtask) {
    -                        selectAndFocusTask(selectedSubtask);
    -                    } else if (currentTask.subtasks.length > 0) {
    -                        // If for some reason the previous subtask isn't found, select the first subtask
    -                        selectAndFocusTask(currentTask.subtasks[0]);
    -                    } else {
    -                        selectAndFocusTask(currentTask);
    -                    }
    -                    currentTask.selectedSubtaskId = currentTaskId;
    -                }
    -            }
    -
    -            function setActiveTask(input, task) {
    -                document.querySelectorAll('.active').forEach(el => el.classList.remove('active'));
    -                input.closest('.task-container').classList.add('active');
    -                if (task !== currentTask) {
    -                    currentTask.selectedSubtaskId = task.id;
    -                }
    -                updateBreadcrumbs(task);
    -            }
    -
    -            function updateBreadcrumbs(selectedTask) {
    -                const breadcrumbsContainer = document.getElementById('breadcrumbs');
    -                const trail = generateBreadcrumbs(taskPath[0], taskPath, selectedTask.id);
    -                breadcrumbsContainer.textContent = trail;
    -            }
    -
    -            function renderCurrentView() {
    -                appContainer.innerHTML = '';
    -                currentTask = taskPath[taskPath.length - 1];
    -
    -                updateBreadcrumbs(currentTask);
    -                updatePageTitle(currentTask);
    -
    -                const parentElement = createTaskElement(currentTask, true);
    -                appContainer.appendChild(parentElement);
    -
    -                const subtasksList = document.createElement('ul');
    -                currentTask.subtasks.forEach(subtask => {
    -                    const li = document.createElement('li');
    -                    li.appendChild(createTaskElement(subtask));
    -                    subtasksList.appendChild(li);
    -                });
    -                appContainer.appendChild(subtasksList);
    -
    -                const parentCheckbox = parentElement.querySelector('input[type="checkbox"]');
    -                updateCheckboxState(parentCheckbox, currentTask.state);
    -
    -                if (currentTask.selectedSubtaskId) {
    -                    const selectedTask = currentTask.subtasks.find(t => t.id === currentTask.selectedSubtaskId);
    -                    if (selectedTask) {
    -                        selectAndFocusTask(selectedTask);
    -                    }
    -                }
    -            }
    -
    -            function copyActiveTaskText(e) {
    -                // Check if the key combination is Ctrl+C (Windows) or Cmd+C (Mac)
    -                if ((e.ctrlKey || e.metaKey) && e.key === 'c') {
    -                    const activeTaskInput = document.querySelector('.task-container.active input[type="text"]');
    -                    if (activeTaskInput) {
    -                        // Check if there's a selection within the active task input
    -                        const selectedText = activeTaskInput.value.substring(activeTaskInput.selectionStart, activeTaskInput.selectionEnd);
    -                        
    -                        const textToCopy = selectedText || activeTaskInput.value;
    -                        
    -                        e.preventDefault(); // Prevent default copy behavior
    -                        navigator.clipboard.writeText(textToCopy);
    -                    }
    -                }
    -            }
    -
    -            function updatePageTitle(task) {
    -                document.title = task.text || '?';
    -            }
    -
    -            function isLastSubtask(task) {
    -                const parentTask = findParentTask(task);
    -                if (!parentTask) return false;
    -                return parentTask.subtasks[parentTask.subtasks.length - 1].id === task.id;
    -            }
    -
    -            renderCurrentView();
    -        });
    -    </script>
429 +					updateBreadcrumbs(currentTask);
430 +					renderCurrentView();
431 +					const selectedSubtask = subtask.selectedSubtaskId ? 
432 +						subtask.subtasks.find(t => t.id === subtask.selectedSubtaskId) : 
433 +						subtask.subtasks[0];
434 +					selectAndFocusTask(selectedSubtask);
435 +				} else {
436 +					addNewSubtask(subtask);
437 +					currentTask.selectedSubtaskId = subtask.id;
438 +					taskPath.push(subtask);
439 +					currentTask = subtask;
440 +					updateBreadcrumbs(currentTask);
441 +					renderCurrentView();
442 +					selectAndFocusTask(subtask.subtasks[0]);
443 +				}
444 +			}
445 +
446 +			function navigateToParentTask() {
447 +				if (taskPath.length > 1) {
448 +					const currentTaskId = currentTask.id;
449 +					taskPath.pop();
450 +					currentTask = taskPath[taskPath.length - 1];
451 +					updateParentTaskState(currentTask);
452 +					updateBreadcrumbs(currentTask);
453 +					renderCurrentView();
454 +					const selectedSubtask = currentTask.subtasks.find(t => t.id === currentTaskId);
455 +					if (selectedSubtask) {
456 +						selectAndFocusTask(selectedSubtask);
457 +					} else if (currentTask.subtasks.length > 0) {
458 +						selectAndFocusTask(currentTask.subtasks[0]);
459 +					} else {
460 +						selectAndFocusTask(currentTask);
461 +					}
462 +					currentTask.selectedSubtaskId = currentTaskId;
463 +				}
464 +			}
465 +
466 +			function setActiveTask(input, task) {
467 +				document.querySelectorAll('.active').forEach(el => el.classList.remove('active'));
468 +				input.closest('.task-container').classList.add('active');
469 +				if (task !== currentTask) {
470 +					currentTask.selectedSubtaskId = task.id;
471 +				}
472 +				updateBreadcrumbs(task);
473 +			}
474 +
475 +			function updateBreadcrumbs(selectedTask) {
476 +				const breadcrumbsContainer = document.getElementById('breadcrumbs');
477 +				const trail = generateBreadcrumbs(taskPath[0], taskPath, selectedTask.id);
478 +				breadcrumbsContainer.textContent = trail;
479 +			}
480 +
481 +			function renderCurrentView() {
482 +				appContainer.innerHTML = '';
483 +				currentTask = taskPath[taskPath.length - 1];
484 +
485 +				updateBreadcrumbs(currentTask);
486 +				updatePageTitle(currentTask);
487 +
488 +				const parentElement = createTaskElement(currentTask, true);
489 +				appContainer.appendChild(parentElement);
490 +
491 +				const subtasksList = document.createElement('ul');
492 +				currentTask.subtasks.forEach(subtask => {
493 +					const li = document.createElement('li');
494 +					li.appendChild(createTaskElement(subtask));
495 +					subtasksList.appendChild(li);
496 +				});
497 +				appContainer.appendChild(subtasksList);
498 +
499 +				const parentCheckbox = parentElement.querySelector('input[type="checkbox"]');
500 +				updateCheckboxState(parentCheckbox, currentTask.state);
501 +
502 +				if (currentTask.selectedSubtaskId) {
503 +					const selectedTask = currentTask.subtasks.find(t => t.id === currentTask.selectedSubtaskId);
504 +					if (selectedTask) {
505 +						selectAndFocusTask(selectedTask);
506 +					}
507 +				}
508 +			}
509 +
510 +			function copyActiveTaskText(e) {
511 +				// Check if the key combination is Ctrl+C (Windows) or Cmd+C (Mac)
512 +				if ((e.ctrlKey || e.metaKey) && e.key === 'c') {
513 +					const activeTaskInput = document.querySelector('.task-container.active input[type="text"]');
514 +					if (activeTaskInput) {
515 +						// Check if there's a selection within the active task input
516 +						const selectedText = activeTaskInput.value.substring(activeTaskInput.selectionStart, activeTaskInput.selectionEnd);
517 +						
518 +						const textToCopy = selectedText || activeTaskInput.value;
519 +						
520 +						e.preventDefault(); // Prevent default copy behavior
521 +						navigator.clipboard.writeText(textToCopy);
522 +					}
523 +				}
524 +			}
525 +
526 +			function updatePageTitle(task) {
527 +				document.title = task.text || '?';
528 +			}
529 +
530 +			function isLastSubtask(task) {
531 +				const parentTask = findParentTask(task);
532 +				if (!parentTask) return false;
533 +				return parentTask.subtasks[parentTask.subtasks.length - 1].id === task.id;
534 +			}
535 +
536 +			renderCurrentView();
537 +		});
538 +	</script>
539  </head>
540  <body>
    -    <div id="breadcrumbs"></div>
    -    <div id="app-container"></div>
541 +	<div id="breadcrumbs"></div>
542 +	<div id="app-container"></div>
543  </body>
544  </html>