feat(ui): diff modal with file sidebar and tinted hunks

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
mika kuns
2026-04-20 10:30:03 +02:00
parent f94bb35db7
commit 4d68543cf2
8 changed files with 455 additions and 5 deletions

View File

@@ -4,7 +4,9 @@ using CommunityToolkit.Mvvm.Input;
using ClaudeDo.Data;
using ClaudeDo.Data.Repositories;
using ClaudeDo.Ui.Services;
using ClaudeDo.Ui.ViewModels.Modals;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.DependencyInjection;
namespace ClaudeDo.Ui.ViewModels.Islands;
@@ -12,6 +14,7 @@ public sealed partial class DetailsIslandViewModel : ViewModelBase
{
private readonly IDbContextFactory<ClaudeDoDbContext> _dbFactory;
private readonly WorkerClient _worker;
private readonly IServiceProvider _services;
// Current task row (set by IslandsShellViewModel via Bind)
[ObservableProperty] private TaskRowViewModel? _task;
@@ -35,10 +38,17 @@ public sealed partial class DetailsIslandViewModel : ViewModelBase
// The task ID we are currently subscribed to for live log messages
private string? _subscribedTaskId;
public DetailsIslandViewModel(IDbContextFactory<ClaudeDoDbContext> dbFactory, WorkerClient worker)
// Set by the view so OpenDiffCommand can show the modal as a dialog
public Func<DiffModalViewModel, System.Threading.Tasks.Task>? ShowDiffModal { get; set; }
// Set by the view so OpenWorktreeCommand can show the modal as a dialog
public Func<WorktreeModalViewModel, System.Threading.Tasks.Task>? ShowWorktreeModal { get; set; }
public DetailsIslandViewModel(IDbContextFactory<ClaudeDoDbContext> dbFactory, WorkerClient worker, IServiceProvider services)
{
_dbFactory = dbFactory;
_worker = worker;
_services = services;
// Subscribe once; filter by current task id inside the handler
_worker.TaskMessageEvent += OnTaskMessage;
@@ -99,6 +109,38 @@ public sealed partial class DetailsIslandViewModel : ViewModelBase
Subtasks.Add(new SubtaskRowViewModel { Id = s.Id, Title = s.Title, Done = s.Completed });
}
[RelayCommand(CanExecute = nameof(CanOpenDiff))]
private async System.Threading.Tasks.Task OpenDiffAsync()
{
if (WorktreePath == null || ShowDiffModal == null) return;
var diffVm = new DiffModalViewModel(_services.GetRequiredService<ClaudeDo.Data.Git.GitService>())
{
WorktreePath = WorktreePath,
};
await diffVm.LoadAsync();
await ShowDiffModal(diffVm);
}
private bool CanOpenDiff() => WorktreePath != null;
[RelayCommand(CanExecute = nameof(CanOpenWorktree))]
private async System.Threading.Tasks.Task OpenWorktreeAsync()
{
if (WorktreePath == null || ShowWorktreeModal == null) return;
var vm = _services.GetRequiredService<WorktreeModalViewModel>();
vm.WorktreePath = WorktreePath;
await vm.LoadAsync();
await ShowWorktreeModal(vm);
}
private bool CanOpenWorktree() => WorktreePath != null;
partial void OnWorktreePathChanged(string? value)
{
OpenDiffCommand.NotifyCanExecuteChanged();
OpenWorktreeCommand.NotifyCanExecuteChanged();
}
[RelayCommand]
private async System.Threading.Tasks.Task SendPromptAsync()
{