feat(mission-control): rename sessions inline in the Recent sessions flyout
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Sonnet 5.5
parent
d9355383a4
commit
5bf08873bd
@@ -326,14 +326,18 @@ public sealed partial class MissionControlViewModel : ViewModelBase, IDisposable
|
||||
{
|
||||
var time = DateTime.SpecifyKind(s.StartedAt, DateTimeKind.Utc).ToLocalTime().ToString("g");
|
||||
var briefPath = s.BriefPath;
|
||||
RecentSessions.Add(new RecentSessionViewModel
|
||||
RecentSessionViewModel row = null!;
|
||||
row = new RecentSessionViewModel
|
||||
{
|
||||
SessionId = s.SessionId,
|
||||
Title = s.Title,
|
||||
Meta = isHandoff ? $"{Loc.T("missionControl.handoffSession")} · {time}" : $"{time} · {s.Cwd}",
|
||||
IsHandoff = isHandoff,
|
||||
ResumeCommand = new RelayCommand(() => ResumeSession(s, taskCurrent.Contains(s.SessionId))),
|
||||
ResumeCommand = new RelayCommand(() => ResumeSession(s, row.Title, taskCurrent.Contains(s.SessionId))),
|
||||
ShowBriefCommand = briefPath is null ? null : new RelayCommand(() => ShowBrief(briefPath)),
|
||||
});
|
||||
CommitRenameCommand = new RelayCommand(() => _ = RenameSessionAsync(row)),
|
||||
};
|
||||
RecentSessions.Add(row);
|
||||
}
|
||||
}
|
||||
catch (Exception ex) { ErrorReported?.Invoke(Loc.T("missionControl.queueRefreshFailed", ex.Message)); }
|
||||
@@ -365,7 +369,7 @@ public sealed partial class MissionControlViewModel : ViewModelBase, IDisposable
|
||||
|
||||
// A task's current session reopens its task tile (deduped, same worktree guards); any other
|
||||
// session gets a fresh ad-hoc tile resuming it in its recorded cwd.
|
||||
private void ResumeSession(MissionControlSessionEntity session, bool isTaskCurrent)
|
||||
private void ResumeSession(MissionControlSessionEntity session, string title, bool isTaskCurrent)
|
||||
{
|
||||
if (session.TaskId is { } taskId && isTaskCurrent)
|
||||
{
|
||||
@@ -374,10 +378,27 @@ public sealed partial class MissionControlViewModel : ViewModelBase, IDisposable
|
||||
}
|
||||
var paneId = Guid.NewGuid().ToString("n");
|
||||
var sessionId = session.SessionId;
|
||||
AddConPtyPane(new ConPtyPaneViewModel(null, session.Title,
|
||||
AddConPtyPane(new ConPtyPaneViewModel(null, title,
|
||||
() => DescribeAsync(() => _worker.GetResumeSessionLaunchSpecAsync(sessionId, paneId))) { IdentityKey = paneId });
|
||||
}
|
||||
|
||||
/// <summary>Commits an inline rename: trims, ignores empty/unchanged input, persists the title.</summary>
|
||||
internal async System.Threading.Tasks.Task RenameSessionAsync(RecentSessionViewModel row)
|
||||
{
|
||||
if (!row.IsEditing) return;
|
||||
row.IsEditing = false;
|
||||
|
||||
var title = row.EditText.Trim();
|
||||
if (title.Length == 0 || title == row.Title) return;
|
||||
try
|
||||
{
|
||||
await using var ctx = await _dbFactory.CreateDbContextAsync();
|
||||
await new MissionControlSessionRepository(ctx).RenameAsync(row.SessionId, title);
|
||||
row.Title = title;
|
||||
}
|
||||
catch (Exception ex) { ErrorReported?.Invoke(Loc.T("missionControl.renameFailed", ex.Message)); }
|
||||
}
|
||||
|
||||
private void ShowBrief(string briefPath)
|
||||
{
|
||||
var (ok, error) = ShellOpen.Path(briefPath);
|
||||
@@ -941,9 +962,28 @@ public sealed partial class RunningOperationViewModel : ObservableObject
|
||||
}
|
||||
|
||||
/// <summary>One row in the "Recent sessions" flyout.</summary>
|
||||
public sealed class RecentSessionViewModel
|
||||
public sealed partial class RecentSessionViewModel : ObservableObject
|
||||
{
|
||||
public required string Title { get; init; }
|
||||
public required string SessionId { get; init; }
|
||||
/// <summary>Display title; updated in place once a rename is persisted.</summary>
|
||||
[ObservableProperty] private string _title = "";
|
||||
/// <summary>True while the inline title TextBox is shown.</summary>
|
||||
[ObservableProperty] private bool _isEditing;
|
||||
/// <summary>The TextBox's working value, kept apart from <see cref="Title"/> so Escape needs no restore.</summary>
|
||||
[ObservableProperty] private string _editText = "";
|
||||
/// <summary>Commits <see cref="EditText"/> as the new title.</summary>
|
||||
public required IRelayCommand CommitRenameCommand { get; init; }
|
||||
|
||||
/// <summary>Switches the row into inline edit mode, seeded with the current title.</summary>
|
||||
public void BeginEdit()
|
||||
{
|
||||
EditText = Title;
|
||||
IsEditing = true;
|
||||
}
|
||||
|
||||
/// <summary>Leaves edit mode without saving.</summary>
|
||||
public void CancelEdit() => IsEditing = false;
|
||||
|
||||
/// <summary>Start time plus cwd (origin) or the handoff label (handoff).</summary>
|
||||
public required string Meta { get; init; }
|
||||
/// <summary>Indents the row under its chain's origin session.</summary>
|
||||
|
||||
Reference in New Issue
Block a user