fix(ui): warn and block save when a list's working dir isn't a git repo
Reuses RepoScanner.IsRepo (now public) to validate WorkingDir whenever it changes in ListSettingsModalViewModel — Browse or typing. A missing folder or a non-repo folder shows an inline warning and gates Save via the same CanExecute pattern the load-failure gate already uses; an empty WorkingDir is untouched. Previously this only surfaced as a Failed task deep in WorktreeManager on first run. Also localizes the two hardcoded EN strings in the same file (delete confirm, planning-sessions block) into vm.listSettings.* keys.
This commit is contained in:
@@ -39,6 +39,11 @@ public sealed partial class ListSettingsModalViewModel : ViewModelBase
|
||||
|
||||
[ObservableProperty] private string _name = "";
|
||||
[ObservableProperty] private string _workingDir = "";
|
||||
// Recomputed whenever WorkingDir changes (typing or Browse) — RepoScanner.IsRepo is the same
|
||||
// check RepoImport uses, so a folder either scans in there or warns here, never neither.
|
||||
[ObservableProperty]
|
||||
[NotifyCanExecuteChangedFor(nameof(SaveCommand))]
|
||||
private string _workingDirWarning = "";
|
||||
[ObservableProperty] private string _defaultCommitType = CommitTypeRegistry.DefaultType;
|
||||
// A manual list holds reminders: tasks created here start out manual (TaskEntity.IsManual).
|
||||
[ObservableProperty] private bool _isManual;
|
||||
@@ -250,9 +255,20 @@ public sealed partial class ListSettingsModalViewModel : ViewModelBase
|
||||
}
|
||||
}
|
||||
|
||||
private bool CanSave() => !IsLoading && !_loadFailed;
|
||||
private bool CanSave() => !IsLoading && !_loadFailed && (IsFolder || string.IsNullOrEmpty(WorkingDirWarning));
|
||||
private bool CanDelete() => !IsLoading;
|
||||
|
||||
// A manual list without a WorkingDir is untouched (empty is always valid) — this only fires
|
||||
// for the "picked a folder that turns out not to be a repo" case the audit found: it would
|
||||
// otherwise only surface as a Failed task the first time the worker tries to use it.
|
||||
partial void OnWorkingDirChanged(string value)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(value)) { WorkingDirWarning = ""; return; }
|
||||
WorkingDirWarning = !Directory.Exists(value)
|
||||
? Loc.T("vm.listSettings.workingDirMissing")
|
||||
: RepoScanner.IsRepo(value) ? "" : Loc.T("vm.listSettings.workingDirNotRepo");
|
||||
}
|
||||
|
||||
[RelayCommand(CanExecute = nameof(CanSave))]
|
||||
private async Task SaveAsync()
|
||||
{
|
||||
@@ -330,7 +346,7 @@ public sealed partial class ListSettingsModalViewModel : ViewModelBase
|
||||
var displayName = string.IsNullOrWhiteSpace(Name) ? Loc.T("vm.listSettings.untitled") : Name;
|
||||
if (ConfirmAsync is not null)
|
||||
{
|
||||
var ok = await ConfirmAsync($"Delete list \"{displayName}\" and all its tasks? This cannot be undone.");
|
||||
var ok = await ConfirmAsync(Loc.T("vm.listSettings.confirmDeleteList", displayName));
|
||||
if (!ok) return;
|
||||
}
|
||||
|
||||
@@ -347,7 +363,7 @@ public sealed partial class ListSettingsModalViewModel : ViewModelBase
|
||||
|| ex.InnerException?.Message.Contains("FOREIGN KEY", StringComparison.OrdinalIgnoreCase) == true))
|
||||
{
|
||||
if (ShowErrorAsync is not null)
|
||||
await ShowErrorAsync("This list has planning sessions with child tasks. Discard those first, then delete the list.");
|
||||
await ShowErrorAsync(Loc.T("vm.listSettings.deleteBlockedPlanning"));
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user