summaryrefslogtreecommitdiff
path: root/makima/frontend/src/components/mesh/TaskDetail.tsx
diff options
context:
space:
mode:
authorsoryu <soryu@soryu.co>2026-03-09 17:20:52 +0000
committerGitHub <noreply@github.com>2026-03-09 17:20:52 +0000
commitf49aaa39a32661b54c109ba002d24cbdf73f4ea3 (patch)
tree457f763ebf0eb5f8d0c66b147f8de5acf8e378fe /makima/frontend/src/components/mesh/TaskDetail.tsx
parentafaae8aba719bf74404a64b57426ecc6a7e70775 (diff)
downloadsoryu-f49aaa39a32661b54c109ba002d24cbdf73f4ea3.tar.gz
soryu-f49aaa39a32661b54c109ba002d24cbdf73f4ea3.zip
feat: worktree diff/commit endpoints and frontend diff viewing (#88)
* feat: soryu-co/soryu - makima: Fix worktree info failing when origin ref is missing * WIP: heartbeat checkpoint * WIP: heartbeat checkpoint * WIP: heartbeat checkpoint * feat: soryu-co/soryu - makima: Add worktree commit endpoint and diff endpoint for regular users * feat: soryu-co/soryu - makima: Add frontend diff viewing with clickable worktree files
Diffstat (limited to 'makima/frontend/src/components/mesh/TaskDetail.tsx')
-rw-r--r--makima/frontend/src/components/mesh/TaskDetail.tsx41
1 files changed, 39 insertions, 2 deletions
diff --git a/makima/frontend/src/components/mesh/TaskDetail.tsx b/makima/frontend/src/components/mesh/TaskDetail.tsx
index fdcc58b..00719e2 100644
--- a/makima/frontend/src/components/mesh/TaskDetail.tsx
+++ b/makima/frontend/src/components/mesh/TaskDetail.tsx
@@ -1,6 +1,6 @@
import { useState, useCallback, useMemo, useEffect } from "react";
import type { TaskWithSubtasks, TaskStatus, TaskSummary, CompletionAction, DaemonDirectory } from "../../lib/api";
-import { retryCompletionAction, getDaemonDirectories, cloneWorktree } from "../../lib/api";
+import { retryCompletionAction, getDaemonDirectories, cloneWorktree, getWorktreeDiff } from "../../lib/api";
import { SubtaskTree, SubtaskProgressBar, calculateTreeStats } from "./SubtaskTree";
import { OverlayDiffViewer } from "./OverlayDiffViewer";
import { PRPreview } from "./PRPreview";
@@ -136,6 +136,9 @@ export function TaskDetail({
);
const [showDiff, setShowDiff] = useState(false);
const [showPRPreview, setShowPRPreview] = useState(false);
+ const [worktreeFileDiff, setWorktreeFileDiff] = useState<string | null>(null);
+ const [worktreeFileDiffPath, setWorktreeFileDiffPath] = useState<string | null>(null);
+ const [worktreeFileDiffLoading, setWorktreeFileDiffLoading] = useState(false);
const [useTreeView, setUseTreeView] = useState(false);
// Track which subtask is expanded for inline editing
const [expandedSubtaskId, setExpandedSubtaskId] = useState<string | null>(null);
@@ -153,6 +156,22 @@ export function TaskDetail({
// Track branch modal state
const [showBranchModal, setShowBranchModal] = useState(false);
+ // Handle clicking a file in the worktree panel to show its diff
+ const handleWorktreeFileClick = useCallback(async (filePath: string) => {
+ setWorktreeFileDiffLoading(true);
+ setWorktreeFileDiffPath(filePath);
+ setWorktreeFileDiff(null);
+ try {
+ const result = await getWorktreeDiff(task.id, filePath);
+ setWorktreeFileDiff(result.diff);
+ } catch (e) {
+ console.error("Failed to fetch worktree diff:", e);
+ setWorktreeFileDiff("");
+ } finally {
+ setWorktreeFileDiffLoading(false);
+ }
+ }, [task.id]);
+
// Check if task is running
const isTaskRunning = task.status === "running" || task.status === "initializing" || task.status === "starting";
// Check if task is in a terminal state (can be continued/reopened)
@@ -897,7 +916,7 @@ export function TaskDetail({
{/* Worktree Files Panel - show changed files in the worktree */}
{(task.status === "done" || task.status === "failed" || task.status === "merged" || task.status === "running") && (
- <WorktreeFilesPanel taskId={task.id} />
+ <WorktreeFilesPanel taskId={task.id} onFileClick={handleWorktreeFileClick} />
)}
{/* Patches List Panel - show exported patches for this task */}
@@ -920,6 +939,24 @@ export function TaskDetail({
</div>
)}
+ {/* Worktree File Diff Modal */}
+ {(worktreeFileDiff !== null || worktreeFileDiffLoading) && (
+ <div className="fixed inset-0 z-50 flex items-center justify-center bg-black/50 p-4">
+ <div className="max-w-4xl w-full max-h-[80vh]">
+ <OverlayDiffViewer
+ diff={worktreeFileDiff || ""}
+ loading={worktreeFileDiffLoading}
+ onClose={() => {
+ setWorktreeFileDiff(null);
+ setWorktreeFileDiffPath(null);
+ setWorktreeFileDiffLoading(false);
+ }}
+ title={worktreeFileDiffPath ? `Diff: ${worktreeFileDiffPath}` : "File Diff"}
+ />
+ </div>
+ </div>
+ )}
+
{/* PR Preview Modal */}
{showPRPreview && (
<div className="fixed inset-0 z-50 flex items-center justify-center bg-black/50 p-4">