fix(ui): persist title edits from the detail pane
EditableTitle had no save handler at all (only EditableDescription did), so retitling a task in the details island was silently discarded on rebind. Mirror the debounced description save, capturing the row so a task switch mid-debounce cannot retitle the wrong task.
This commit is contained in:
@@ -258,6 +258,9 @@ public sealed partial class DetailsIslandViewModel : ViewModelBase, IDisposable
|
||||
private bool _suppressDescSave;
|
||||
private CancellationTokenSource? _descSaveCts;
|
||||
|
||||
private bool _suppressTitleSave;
|
||||
private CancellationTokenSource? _titleSaveCts;
|
||||
|
||||
// Set by shell so CloseDetailCommand can clear SelectedTask
|
||||
public Action? CloseDetail { get; set; }
|
||||
|
||||
@@ -430,6 +433,39 @@ public sealed partial class DetailsIslandViewModel : ViewModelBase, IDisposable
|
||||
}
|
||||
}
|
||||
|
||||
partial void OnEditableTitleChanged(string value)
|
||||
{
|
||||
if (_suppressTitleSave || Task is null) return;
|
||||
_titleSaveCts?.Cancel();
|
||||
_titleSaveCts = new CancellationTokenSource();
|
||||
// Capture the row so a task switch mid-debounce cannot retitle the new task.
|
||||
_ = SaveTitleAsync(Task, value, _titleSaveCts.Token);
|
||||
}
|
||||
|
||||
private async System.Threading.Tasks.Task SaveTitleAsync(
|
||||
TaskRowViewModel row, string value, CancellationToken ct)
|
||||
{
|
||||
try
|
||||
{
|
||||
await System.Threading.Tasks.Task.Delay(400, ct);
|
||||
var title = value?.Trim();
|
||||
// An empty title would make the row unidentifiable — keep the stored one.
|
||||
if (string.IsNullOrEmpty(title)) return;
|
||||
await using var ctx = _dbFactory.CreateDbContext();
|
||||
var repo = new TaskRepository(ctx);
|
||||
var entity = await repo.GetByIdAsync(row.Id);
|
||||
if (entity is null || entity.Title == title) return;
|
||||
entity.Title = title;
|
||||
await repo.UpdateAsync(entity);
|
||||
ct.ThrowIfCancellationRequested();
|
||||
row.Title = title;
|
||||
if (ReferenceEquals(Task, row))
|
||||
Merge.SyncTaskContext(row.Id, title, row.IsPlanningParent);
|
||||
}
|
||||
catch (OperationCanceledException) { }
|
||||
catch { }
|
||||
}
|
||||
|
||||
partial void OnEditableDescriptionChanged(string value)
|
||||
{
|
||||
if (_suppressDescSave || Task is null) return;
|
||||
@@ -525,7 +561,9 @@ public sealed partial class DetailsIslandViewModel : ViewModelBase, IDisposable
|
||||
ct.ThrowIfCancellationRequested();
|
||||
if (entity == null) return;
|
||||
|
||||
EditableTitle = entity.Title;
|
||||
_suppressTitleSave = true;
|
||||
try { EditableTitle = entity.Title; }
|
||||
finally { _suppressTitleSave = false; }
|
||||
_suppressDescSave = true;
|
||||
try { EditableDescription = entity.Description ?? ""; }
|
||||
finally { _suppressDescSave = false; }
|
||||
|
||||
Reference in New Issue
Block a user