diff --git a/src/Context.svelte.ts b/src/Context.svelte.ts index ce81846..5ef50e1 100644 --- a/src/Context.svelte.ts +++ b/src/Context.svelte.ts @@ -65,8 +65,17 @@ export class Context { this.updateTaskPositions(); } - public setDraggedTaskId = (id: number) => { - this.draggedTaskId = id; + public startTaskDragging = (e: PointerEvent, taskId: TaskId) => { + this.draggedTaskId = taskId; + this.taskDraggingManager.onPointerDown(e); + }; + + public finishTaskDragging = (e: PointerEvent, updatePositions = false) => { + this.draggedTaskId = NoTaskId; + this.taskDraggingManager.onPointerUp(e); + if (updatePositions) { + this.updateTaskPositions(); + } }; public setScale(scale: number) { diff --git a/src/TaskmapView.ts b/src/TaskmapView.ts index bc89264..ccb1501 100644 --- a/src/TaskmapView.ts +++ b/src/TaskmapView.ts @@ -40,6 +40,14 @@ export class TaskmapView extends TextFileView { }); } + getFile() { + if (this.file) { + return this.file; + } else { + throw new Error(); + } + } + getFilePath(): string { if (this.file) { return this.file.path; diff --git a/src/components/AddTaskButton.svelte b/src/components/AddTaskButton.svelte index 98b03e9..8c8563e 100644 --- a/src/components/AddTaskButton.svelte +++ b/src/components/AddTaskButton.svelte @@ -10,9 +10,9 @@ let entered = $state(false); function addButtonPressed(event: PointerEvent) { + console.log('addButtonPressed'); context.addTask(taskId); - context.taskDraggingManager.onPointerUp(event); - context.setDraggedTaskId(NoTaskId); + context.finishTaskDragging(event); event.stopPropagation(); } @@ -33,7 +33,7 @@ class:ready={taskData.status === StatusCode.READY} class:in-progress={taskData.status === StatusCode.IN_PROGRESS} class:done={taskData.status === StatusCode.DONE} - onpointerdown={()=>{}} + onpointerdown={(e: PointerEvent) => e.stopPropagation()} onpointerup={addButtonPressed} viewBox="0 0 24 24" > diff --git a/src/components/HideBranchButton.svelte b/src/components/HideBranchButton.svelte index f3d40ea..8172200 100644 --- a/src/components/HideBranchButton.svelte +++ b/src/components/HideBranchButton.svelte @@ -12,9 +12,7 @@ function hidePressed(event: PointerEvent) { context.projectData.toggleHidden(taskId); event.stopPropagation(); - context.taskDraggingManager.onPointerUp(event); - context.setDraggedTaskId(NoTaskId); - context.updateTaskPositions(); + context.finishTaskDragging(event, true); } @@ -30,12 +28,12 @@ > {#if taskData.hidden} {}} + onpointerdown={(e) => e.stopPropagation()} onpointerup={hidePressed} /> {:else if entered && !taskData.hidden} {}} + onpointerdown={(e) => e.stopPropagation()} onpointerup={hidePressed} /> {/if} diff --git a/src/components/Task.svelte b/src/components/Task.svelte index 717d58b..fb5e301 100644 --- a/src/components/Task.svelte +++ b/src/components/Task.svelte @@ -46,8 +46,7 @@ // const input = (document.getElementById('titleInput') as HTMLInputElement); // input.disabled = false; } - context.taskDraggingManager.onPointerUp(event); - context.setDraggedTaskId(NoTaskId); + context.finishTaskDragging(event); context.updateTaskPositions(); event.stopPropagation(); } @@ -75,8 +74,9 @@ class:unselect={isUnselected} onmouseenter={() => isHovered = true} onmouseleave={() => isHovered = false} - onpointerdown={(event: PointerEvent) => { - context.setDraggedTaskId(taskId); + onpointerdown={(e: PointerEvent) => { + context.startTaskDragging(e, taskId); + e.stopPropagation(); }} onpointerup={onPointerUp} onblur={() => finishEditing(true)} @@ -92,7 +92,7 @@ taskData.name = newContent; context.save(); }} - sourcePath={context.view.getFilePath()} + file={context.view.getFile()} /> {#if !context.taskDraggingManager.isDragging} @@ -120,7 +120,7 @@ text-align: center; color: white; font-size: 20px; - font-family: "Segoe UI"; + font-family: var(--font-text); line-height: 1.5; width: 280px; height: 80px; diff --git a/src/components/TaskText.svelte b/src/components/TaskText.svelte index 10a642e..63a7c06 100644 --- a/src/components/TaskText.svelte +++ b/src/components/TaskText.svelte @@ -3,7 +3,6 @@ import {MarkdownRenderer, Component, App, type TFile} from "obsidian"; import {LinkSuggest} from "../LinkSuggest"; import type {Context} from "../Context.svelte.js"; - import {NoTaskId} from "../NodePositionsCalculator"; // PROPS let { @@ -12,7 +11,7 @@ context, app, content, - sourcePath, + file, onSave }: { taskId: number, @@ -20,7 +19,7 @@ context: Context, app: App; content: string; - sourcePath: string; + file: TFile; onSave: (newContent: string) => void } = $props(); @@ -63,8 +62,7 @@ if (isDragging) { return; } - context.taskDraggingManager.onPointerUp(e); - context.setDraggedTaskId(NoTaskId); + context.finishTaskDragging(e); console.log('task text clicked'); const target = e.target as HTMLElement; @@ -117,19 +115,30 @@ hoverParent: textPreviewEl, targetEl: link, linktext: link.getAttribute("data-href"), - sourcePath: sourcePath + sourcePath: "" }); } } async function renderMarkdown() { textPreviewEl.empty(); // Clear previous render - await MarkdownRenderer.render( - app, - content, - textPreviewEl, - sourcePath, - component - ); + if (file !== undefined) { + await MarkdownRenderer.render( + app, + `[[${file.path}]]`, + textPreviewEl, + "", + component, + ); + } else { + await MarkdownRenderer.render( + app, + content, + textPreviewEl, + "", + component, + ); + + } // After rendering, find all links and disable their native dragging const links = textPreviewEl.querySelectorAll('a, .internal-link, .external-link'); links.forEach(link => { @@ -222,7 +231,7 @@ background: transparent; resize: none; font-size: 20px; - font-family: "Segoe UI"; + font-family: var(--font-text); line-height: 1.5; /*border: 4px solid #707070;*/ /*border-radius: 22px;*/ diff --git a/src/components/TaskmapContainer.svelte b/src/components/TaskmapContainer.svelte index ef955ed..57e98f1 100644 --- a/src/components/TaskmapContainer.svelte +++ b/src/components/TaskmapContainer.svelte @@ -4,10 +4,11 @@ import Task from "./Task.svelte"; import Panzoom, {type PanzoomObject} from '@panzoom/panzoom' import type {Context} from "../Context.svelte.js"; - import {MouseDown} from "../types"; + import {MouseDown, type Vector2} from "../types"; import Connection from "./Connection.svelte"; import {NoTaskId, RootTaskId, V2} from "../NodePositionsCalculator"; import {TASK_SIZE} from "../Constants"; + import {DraggingManager} from "../DraggingManager.svelte"; let {context}: {context: Context} = $props(); @@ -15,14 +16,8 @@ let sceneEl: HTMLDivElement | null = null; let svgGroupEl: SVGGElement | null = null; let panzoom: PanzoomObject | null = null; - let isDragging = false; - let mouseDown = $state(MouseDown.NONE); // -1 - let startX = 0; - let startY = 0; - let panStartX = 0; - let panStartY = 0; - // let cssTransform = $derived(`translate(${transformState.x}px, ${transformState.y}px) scale(${transformState.scale})`); - // let svgTransform = $derived(`translate(${transformState.x} ${transformState.y}) scale(${transformState.scale})`); + let panstart: Vector2 = {x: 0, y: 0}; + let draggingManager = new DraggingManager([MouseDown.MIDDLE, MouseDown.LEFT]); onMount(async () => { @@ -66,59 +61,44 @@ } function onpointerdown(e: PointerEvent) { - console.log('handlePointerDown', e.pointerId, e.button); - context.taskDraggingManager.onPointerDown(e); - mouseDown = e.button as MouseDown; - if (mouseDown == MouseDown.MIDDLE) { - e.preventDefault(); // prevent auto-scroll - // Capture the pointer so move events continue even if - // the mouse leaves the element during a fast drag - (e.currentTarget as HTMLDivElement).setPointerCapture(e.pointerId); - startX = e.clientX; - startY = e.clientY; - } + // prevent auto-scroll + e.preventDefault(); + draggingManager.onPointerDown(e); + panstart = getPanzoom().getPan(); e.stopPropagation(); } function onpointermove(e: PointerEvent) { console.log('handlePointerMove', e.pointerId, e.button); - context.taskDraggingManager.onPointerMove(e); - context.updateTaskPositions(true); - const deltaX = e.clientX - startX; - const deltaY = e.clientY - startY; - if (mouseDown == MouseDown.MIDDLE && !isDragging) { - // Calculate distance moved - const dist = Math.pow(deltaX, 2) + Math.pow(deltaY, 2); - // If moved more than 5 pixels, it's a drag, not a click - const thrDist = 5; - if (dist > Math.pow(thrDist,2)) { - isDragging = true; - const pan = getPanzoom().getPan(); - panStartX = pan.x; - panStartY = pan.y; - // getPanzoom().handleMove(e); + if (context.draggedTaskId != NoTaskId) { + context.taskDraggingManager.onPointerMove(e); + if (context.taskDraggingManager.isDragging) { + context.updateTaskPositions(true); + } + } else { + draggingManager.onPointerMove(e); + if (draggingManager.isDragging) { + // prevent auto-scroll + e.preventDefault(); + // Capture the pointer so move events continue even if + // the mouse leaves the element during a fast drag + (e.currentTarget as HTMLDivElement).setPointerCapture(e.pointerId); + const scale = getPanzoom().getScale(); + getPanzoom().pan( + panstart.x + draggingManager.deltaX/scale, + panstart.y + draggingManager.deltaY/scale + ); } - } - if (isDragging) { - e.preventDefault(); - const scale = getPanzoom().getScale(); - getPanzoom().pan(panStartX+deltaX/scale, panStartY+deltaY/scale); } e.stopPropagation(); } function onpointerup(e: PointerEvent) { console.log('handlePointerUp', e.pointerId, e.button); - context.taskDraggingManager.onPointerUp(e); - context.setDraggedTaskId(NoTaskId); - context.updateTaskPositions(); - if (e.button as MouseDown == MouseDown.MIDDLE && isDragging) { + if (draggingManager.isDragging) { // Release the pointer capture (e.currentTarget as HTMLDivElement).releasePointerCapture(e.pointerId); - } - mouseDown = MouseDown.NONE; - isDragging = false; - if (e.button as MouseDown == MouseDown.LEFT) { + } else if (e.button as MouseDown == MouseDown.LEFT) { console.log(`Window clicked + ${context.serializeForDebugging()}`); console.log('selectedTaskId ' + context.selectedTaskId); context.pressedButtonCode = -1; @@ -127,6 +107,8 @@ viewportEl!.focus(); e.stopPropagation(); } + draggingManager.onPointerUp(e); + context.finishTaskDragging(e, true); } function getPanzoom() { @@ -140,7 +122,7 @@