Fix mobile drag and drop

This commit is contained in:
2026-01-05 22:13:32 -05:00
parent 16f0e10198
commit f06cc48841

View File

@ -208,6 +208,9 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_GET['api'])) {
transition: all 0.2s;
user-select: none;
position: relative;
display: flex;
align-items: center;
gap: 12px;
}
.task-item.selected {
@ -235,6 +238,53 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_GET['api'])) {
background: #E8E8E8;
}
.drag-handle {
width: 24px;
height: 24px;
cursor: grab;
padding: 4px;
touch-action: none;
user-select: none;
flex-shrink: 0;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
gap: 3px;
}
.drag-handle::before,
.drag-handle::after {
content: '';
width: 18px;
height: 2px;
background: #999;
border-radius: 1px;
}
.drag-handle span {
width: 18px;
height: 2px;
background: #999;
border-radius: 1px;
display: block;
}
.drag-handle:active::before,
.drag-handle:active::after,
.drag-handle:active span {
background: #4A90E2;
}
.drag-handle:active {
cursor: grabbing;
}
.task-content {
flex: 1;
min-width: 0;
}
.task-name {
font-weight: 500;
font-size: 16px;
@ -442,18 +492,29 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_GET['api'])) {
v-for="(task, index) in tasks"
:key="task.id"
:class="['task-item', task.status, { selected: task.selected, dragging: draggedTask === task }]"
:draggable="!task.isSeparator"
@click="!task.isSeparator && toggleTaskSelection(task)"
@dblclick="!task.isSeparator && editSingleTask(task)"
@dragstart="!task.isSeparator && onDragStart(task, $event)"
@dragover="onDragOver(task, $event)"
@drop="onDrop(task, $event)"
@dragend="onDragEnd"
>
<div v-if="task.isSeparator" class="separator"></div>
<template v-else>
<div
class="drag-handle"
draggable="true"
@dragstart="onDragStart(task, $event)"
@dragend="onDragEnd"
@touchstart="onTouchStart(task, $event)"
@touchmove="onTouchMove(task, $event)"
@touchend="onTouchEnd($event)"
@touchcancel="onTouchCancel($event)"
><span></span></div>
<div
class="task-content"
@click="toggleTaskSelection(task)"
@dblclick="editSingleTask(task)"
>
<div class="task-name">{{ task.name }}</div>
<div class="task-notes" v-if="task.firstNoteLine">{{ task.firstNoteLine }}</div>
</div>
</template>
</div>
</div>
@ -523,6 +584,8 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_GET['api'])) {
currentFileName: 'Inbox',
fileMtime: null,
draggedTask: null,
touchDraggedTask: null,
touchStartY: 0,
showFileModal: false,
fileModalTitle: '',
fileModalMode: '',
@ -753,6 +816,61 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_GET['api'])) {
this.draggedTask = null;
},
// Touch drag for mobile
onTouchStart(task, event) {
this.touchDraggedTask = task;
this.touchStartY = event.touches[0].clientY;
// Prevent default to stop scrolling while dragging from handle
event.preventDefault();
},
onTouchMove(task, event) {
if (!this.touchDraggedTask) return;
event.preventDefault();
const touchY = event.touches[0].clientY;
// Find which task element we're over
const elements = document.elementsFromPoint(event.touches[0].clientX, touchY);
for (const el of elements) {
if (el.classList && el.classList.contains('task-item')) {
// Find the task index
const taskItems = Array.from(document.querySelectorAll('.task-item'));
const targetIndex = taskItems.indexOf(el);
if (targetIndex !== -1) {
const targetTask = this.tasks[targetIndex];
if (targetTask && targetTask !== this.touchDraggedTask && !targetTask.isSeparator) {
const draggedIndex = this.tasks.indexOf(this.touchDraggedTask);
if (draggedIndex !== -1 && draggedIndex !== targetIndex) {
// Remove from old position
this.tasks.splice(draggedIndex, 1);
// Insert at new position
const newIndex = draggedIndex < targetIndex ? targetIndex : targetIndex;
this.tasks.splice(newIndex, 0, this.touchDraggedTask);
}
}
}
break;
}
}
},
onTouchEnd(event) {
if (this.touchDraggedTask) {
this.saveFile();
this.touchDraggedTask = null;
}
},
onTouchCancel(event) {
this.touchDraggedTask = null;
},
// Actions
addTask() {
this.editorTitle = 'New Task';