fix(ui): duplizierter Confirm-Dialog mit "Delete"-Knopf – zusammenfuehren und lokalisieren
F4: DetailsIslandView/TasksIslandView hatten je eine view-lokale Confirm/Error-Dialog-Kopie, teils mit hartkodiertem "Delete"-Knopf fuer jede Aktion (inkl. der Stash+Merge-Bestaetigung, die nichts loescht). Beide Kopien entfernt; DetailsIslandViewModel/TasksIslandViewModel routen Confirm/Error jetzt durch den geteilten Dialogs-Seam (IDialogService, propagiert vom Shell wie schon bei Lists/Tasks) statt ueber eine vom Code-behind gesetzte Func-Property. IDialogService.ConfirmAsync bekommt einen optionalen confirmLabel-Parameter (Default: lokalisiertes "Confirm"); nur die echten Delete-Aktionen (Task loeschen, abgeschlossene Tasks leeren) uebergeben das lokalisierte "Delete"-Label. F5: "Cancel"/"Confirm"/"Delete"/"OK" und die Titel "Confirm"/"Error" durch Loc.T mit neuen Keys unter "dialog.*" ersetzt (en.json + de.json). Mission Controls eigene Dialog-Kopie bleibt bestehen (eigenes Fenster, WindowDialogService ist an den Haupt-Owner gebunden) — nur ihre Labels wurden lokalisiert. Out of scope (siehe Task-Beschreibung): die Nachrichtentexte der Dialoge bleiben unlokalisiert.
This commit is contained in:
@@ -28,8 +28,9 @@ public interface IDialogService
|
||||
Task ShowConflictResolverAsync(ConflictResolverViewModel vm);
|
||||
Task ShowLogVisualizerAsync(LogVisualizerViewModel vm);
|
||||
|
||||
/// <summary>Modal yes/no confirmation. Returns true only when confirmed.</summary>
|
||||
Task<bool> ConfirmAsync(string message);
|
||||
/// <summary>Modal yes/no confirmation. Returns true only when confirmed. <paramref name="confirmLabel"/>
|
||||
/// overrides the default localized "Confirm" button text (e.g. a localized "Delete" for destructive actions).</summary>
|
||||
Task<bool> ConfirmAsync(string message, string? confirmLabel = null);
|
||||
|
||||
/// <summary>Modal error notice with a single dismiss button.</summary>
|
||||
Task ShowErrorAsync(string message);
|
||||
|
||||
@@ -291,11 +291,9 @@ public sealed partial class DetailsIslandViewModel : ViewModelBase, IDisposable
|
||||
// Set by shell so DeleteTaskCommand can remove from list
|
||||
public Func<TaskRowViewModel, System.Threading.Tasks.Task>? DeleteFromList { get; set; }
|
||||
|
||||
// Set by the view so DeleteTaskCommand can prompt yes/no before deleting
|
||||
public Func<string, System.Threading.Tasks.Task<bool>>? ConfirmAsync { get; set; }
|
||||
|
||||
// Set by the view so DeleteTaskCommand can show an error message
|
||||
public Func<string, System.Threading.Tasks.Task>? ShowErrorAsync { get; set; }
|
||||
// Set by the shell (mirrors ListsIslandViewModel.Dialogs) so confirm/error prompts go
|
||||
// through the one shared dialog implementation instead of a view-local copy.
|
||||
public IDialogService? Dialogs { get; set; }
|
||||
|
||||
// ── Review ──────────────────────────────────────────────────────────────
|
||||
[ObservableProperty]
|
||||
@@ -1042,9 +1040,9 @@ public sealed partial class DetailsIslandViewModel : ViewModelBase, IDisposable
|
||||
{
|
||||
if (Task == null) return;
|
||||
var row = Task;
|
||||
if (ConfirmAsync != null)
|
||||
if (Dialogs != null)
|
||||
{
|
||||
var ok = await ConfirmAsync($"Delete \"{row.Title}\"? This cannot be undone.");
|
||||
var ok = await Dialogs.ConfirmAsync($"Delete \"{row.Title}\"? This cannot be undone.", Loc.T("dialog.delete"));
|
||||
if (!ok) return;
|
||||
}
|
||||
// Routed through the worker (mirrors the MCP delete_task tool) so a deleted child
|
||||
@@ -1060,14 +1058,14 @@ public sealed partial class DetailsIslandViewModel : ViewModelBase, IDisposable
|
||||
{
|
||||
// Belt and braces: the connection can drop between the CanExecute check and
|
||||
// this call, so a stray throw here must surface, not vanish silently.
|
||||
if (ShowErrorAsync != null)
|
||||
await ShowErrorAsync(ex.Message);
|
||||
if (Dialogs != null)
|
||||
await Dialogs.ShowErrorAsync(ex.Message);
|
||||
return;
|
||||
}
|
||||
if (!deleted)
|
||||
{
|
||||
if (ShowErrorAsync != null)
|
||||
await ShowErrorAsync(error ?? "Delete failed.");
|
||||
if (Dialogs != null)
|
||||
await Dialogs.ShowErrorAsync(error ?? "Delete failed.");
|
||||
return;
|
||||
}
|
||||
if (DeleteFromList != null)
|
||||
@@ -1216,10 +1214,10 @@ public sealed partial class DetailsIslandViewModel : ViewModelBase, IDisposable
|
||||
private async System.Threading.Tasks.Task ResetAndRetryAsync()
|
||||
{
|
||||
if (Task == null) return;
|
||||
if (ConfirmAsync == null) return;
|
||||
if (Dialogs == null) return;
|
||||
|
||||
var branchName = $"claudedo/{Task.Id.Replace("-", "")}";
|
||||
var ok = await ConfirmAsync(
|
||||
var ok = await Dialogs.ConfirmAsync(
|
||||
$"Reset and retry?\nThis discards branch {branchName} (and uncommitted changes), then queues the task to run from the beginning.");
|
||||
if (!ok) return;
|
||||
|
||||
@@ -1279,31 +1277,31 @@ public sealed partial class DetailsIslandViewModel : ViewModelBase, IDisposable
|
||||
// Nothing landed -- the target working dir has uncommitted changes (often another
|
||||
// session's WIP in the shared main checkout). Offer the one-shot stash retry; git
|
||||
// restores the changes itself once the merge is through.
|
||||
if (result?.Status == "dirty_target" && ConfirmAsync != null
|
||||
&& await ConfirmAsync(Loc.T("vm.detailsIsland.stashAndMergeConfirm")))
|
||||
if (result?.Status == "dirty_target" && Dialogs != null
|
||||
&& await Dialogs.ConfirmAsync(Loc.T("vm.detailsIsland.stashAndMergeConfirm")))
|
||||
{
|
||||
ApproveOp.Report(Loc.T("ops.merge.merging"));
|
||||
result = await _worker.ApproveReviewAsync(
|
||||
taskId, Merge.SelectedMergeTarget ?? "", autostash: true);
|
||||
}
|
||||
|
||||
if (result?.Status == "dirty_target" && ShowErrorAsync != null)
|
||||
await ShowErrorAsync(result.ErrorMessage ?? Loc.T("vm.detailsIsland.dirtyTarget"));
|
||||
if (result?.Status == "dirty_target" && Dialogs != null)
|
||||
await Dialogs.ShowErrorAsync(result.ErrorMessage ?? Loc.T("vm.detailsIsland.dirtyTarget"));
|
||||
else if (!hasChildren && result?.Status == "conflict")
|
||||
await _merge.ResolveConflictAsync(taskId, Merge.SelectedMergeTarget ?? "");
|
||||
// The merge itself already landed; the verify command failed, so the task stayed
|
||||
// out of Done. Surface that instead of silently looking like nothing happened.
|
||||
else if (!hasChildren && result?.Status == "verify_failed" && ShowErrorAsync != null)
|
||||
await ShowErrorAsync(result.ErrorMessage ?? Loc.T("vm.detailsIsland.verifyFailed"));
|
||||
else if (!hasChildren && result?.Status == "verify_failed" && Dialogs != null)
|
||||
await Dialogs.ShowErrorAsync(result.ErrorMessage ?? Loc.T("vm.detailsIsland.verifyFailed"));
|
||||
// Nothing landed -- the merge was refused before touching the repo because the
|
||||
// branch would have overwritten an untracked file in the target working directory.
|
||||
else if (!hasChildren && result?.Status == "untracked_collision" && ShowErrorAsync != null)
|
||||
await ShowErrorAsync(result.ErrorMessage ?? Loc.T("vm.detailsIsland.untrackedCollision"));
|
||||
else if (!hasChildren && result?.Status == "untracked_collision" && Dialogs != null)
|
||||
await Dialogs.ShowErrorAsync(result.ErrorMessage ?? Loc.T("vm.detailsIsland.untrackedCollision"));
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
if (ShowErrorAsync != null)
|
||||
await ShowErrorAsync(ex.Message);
|
||||
if (Dialogs != null)
|
||||
await Dialogs.ShowErrorAsync(ex.Message);
|
||||
}
|
||||
finally
|
||||
{
|
||||
@@ -1348,7 +1346,7 @@ public sealed partial class DetailsIslandViewModel : ViewModelBase, IDisposable
|
||||
try { await _worker.SubmitTaskForReviewAsync(Task.Id); }
|
||||
catch (Exception ex)
|
||||
{
|
||||
if (ShowErrorAsync != null) await ShowErrorAsync(ex.Message);
|
||||
if (Dialogs != null) await Dialogs.ShowErrorAsync(ex.Message);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1379,9 +1377,9 @@ public sealed partial class DetailsIslandViewModel : ViewModelBase, IDisposable
|
||||
[RelayCommand]
|
||||
private async System.Threading.Tasks.Task ResetReviewAsync()
|
||||
{
|
||||
if (Task is null || !_worker.IsConnected || ConfirmAsync is null) return;
|
||||
if (Task is null || !_worker.IsConnected || Dialogs is null) return;
|
||||
var branchName = $"claudedo/{Task.Id.Replace("-", "")}";
|
||||
var ok = await ConfirmAsync(
|
||||
var ok = await Dialogs.ConfirmAsync(
|
||||
$"Reset working tree?\nThis discards branch {branchName} (and all changes) and returns the task to Idle.");
|
||||
if (!ok) return;
|
||||
try { await _worker.ResetTaskAsync(Task.Id); }
|
||||
|
||||
@@ -1209,9 +1209,9 @@ public sealed partial class TasksIslandViewModel : ViewModelBase, IDisposable
|
||||
// block removing a completed planning parent together with its done children.
|
||||
var toDelete = completed.OrderByDescending(r => r.IsChild).ToList();
|
||||
|
||||
if (ConfirmAsync is not null)
|
||||
if (Dialogs is not null)
|
||||
{
|
||||
var ok = await ConfirmAsync($"Clear {toDelete.Count} completed task(s)? This cannot be undone.");
|
||||
var ok = await Dialogs.ConfirmAsync($"Clear {toDelete.Count} completed task(s)? This cannot be undone.", Loc.T("dialog.delete"));
|
||||
if (!ok) return;
|
||||
}
|
||||
|
||||
@@ -1339,9 +1339,9 @@ public sealed partial class TasksIslandViewModel : ViewModelBase, IDisposable
|
||||
private async Task DeleteTaskAsync(TaskRowViewModel? row)
|
||||
{
|
||||
if (row is null || row.HasInteractiveSession || _worker is null) return;
|
||||
if (ConfirmAsync is not null)
|
||||
if (Dialogs is not null)
|
||||
{
|
||||
var ok = await ConfirmAsync(Loc.T("vm.tasksIsland.deleteTaskConfirm", row.Title));
|
||||
var ok = await Dialogs.ConfirmAsync(Loc.T("vm.tasksIsland.deleteTaskConfirm", row.Title), Loc.T("dialog.delete"));
|
||||
if (!ok) return;
|
||||
}
|
||||
|
||||
@@ -1653,8 +1653,8 @@ public sealed partial class TasksIslandViewModel : ViewModelBase, IDisposable
|
||||
|
||||
if (outcome.Result == DiscardPlanningResult.BlockedByQueuedChildren)
|
||||
{
|
||||
if (ConfirmAsync is null) return;
|
||||
var ok = await ConfirmAsync(
|
||||
if (Dialogs is null) return;
|
||||
var ok = await Dialogs.ConfirmAsync(
|
||||
$"{outcome.QueuedChildrenCount} child task(s) are queued.\n" +
|
||||
"Dequeue them and discard the planning session?");
|
||||
if (!ok) return;
|
||||
@@ -1663,18 +1663,13 @@ public sealed partial class TasksIslandViewModel : ViewModelBase, IDisposable
|
||||
}
|
||||
else if (outcome.Result == DiscardPlanningResult.BlockedByRunningChildren)
|
||||
{
|
||||
if (ConfirmAsync is null) return;
|
||||
await ConfirmAsync(
|
||||
if (Dialogs is null) return;
|
||||
await Dialogs.ConfirmAsync(
|
||||
$"{outcome.RunningChildrenCount} child task(s) are still running.\n" +
|
||||
"Cancel them first, then try again.");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Wired by the view via <see cref="ShowConfirmAsync"/>. Returns true when the user confirms.
|
||||
/// </summary>
|
||||
public Func<string, Task<bool>>? ConfirmAsync { get; set; }
|
||||
|
||||
private bool CanRunPlanningOperation() => !PlanningOperation.IsRunning;
|
||||
|
||||
[RelayCommand(CanExecute = nameof(CanRunPlanningOperation))]
|
||||
|
||||
@@ -68,7 +68,7 @@ public sealed partial class IslandsShellViewModel : ViewModelBase, IDisposable
|
||||
// Set by MainWindow so a reveal can bring the main window to the foreground.
|
||||
public Action? BringToFront { get; set; }
|
||||
|
||||
// Single dialog seam (set by MainWindow); propagated to the lists island.
|
||||
// Single dialog seam (set by MainWindow); propagated to the islands.
|
||||
private IDialogService? _dialogs;
|
||||
public IDialogService? Dialogs
|
||||
{
|
||||
@@ -78,6 +78,7 @@ public sealed partial class IslandsShellViewModel : ViewModelBase, IDisposable
|
||||
_dialogs = value;
|
||||
if (Lists is not null) Lists.Dialogs = value;
|
||||
if (Tasks is not null) Tasks.Dialogs = value;
|
||||
if (Details is not null) Details.Dialogs = value;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -173,8 +173,6 @@ public partial class DetailsIslandView : UserControl
|
||||
await modal.ShowDialog(owner);
|
||||
};
|
||||
|
||||
vm.ConfirmAsync = ShowConfirmAsync;
|
||||
vm.ShowErrorAsync = ShowErrorDialogAsync;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -213,87 +211,4 @@ public partial class DetailsIslandView : UserControl
|
||||
_descriptionHeights[id] = DetailBodyGrid.RowDefinitions[0].Height.Value;
|
||||
}
|
||||
|
||||
private async System.Threading.Tasks.Task ShowErrorDialogAsync(string message)
|
||||
{
|
||||
var owner = TopLevel.GetTopLevel(this) as Window;
|
||||
if (owner == null) return;
|
||||
|
||||
var ok = new Button { Content = "OK", MinWidth = 90 };
|
||||
|
||||
var dialog = new Window
|
||||
{
|
||||
Title = "Error",
|
||||
Width = 360,
|
||||
SizeToContent = SizeToContent.Height,
|
||||
CanResize = false,
|
||||
WindowStartupLocation = WindowStartupLocation.CenterOwner,
|
||||
ShowInTaskbar = false,
|
||||
Background = this.FindResource("SurfaceBrush") as IBrush,
|
||||
Content = new StackPanel
|
||||
{
|
||||
Spacing = 16,
|
||||
Margin = new Thickness(20),
|
||||
Children =
|
||||
{
|
||||
new TextBlock { Text = message, TextWrapping = TextWrapping.Wrap },
|
||||
new StackPanel
|
||||
{
|
||||
Orientation = Orientation.Horizontal,
|
||||
Spacing = 8,
|
||||
HorizontalAlignment = HorizontalAlignment.Right,
|
||||
Children = { ok }
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
ok.Click += (_, _) => dialog.Close();
|
||||
|
||||
await dialog.ShowDialog(owner);
|
||||
}
|
||||
|
||||
private async System.Threading.Tasks.Task<bool> ShowConfirmAsync(string message)
|
||||
{
|
||||
var owner = TopLevel.GetTopLevel(this) as Window;
|
||||
if (owner == null) return false;
|
||||
|
||||
var tcs = new TaskCompletionSource<bool>();
|
||||
|
||||
var cancel = new Button { Content = "Cancel", MinWidth = 90 };
|
||||
var confirm = new Button { Content = "Delete", MinWidth = 90, Classes = { "danger" } };
|
||||
|
||||
var dialog = new Window
|
||||
{
|
||||
Title = "Confirm",
|
||||
Width = 360,
|
||||
SizeToContent = SizeToContent.Height,
|
||||
CanResize = false,
|
||||
WindowStartupLocation = WindowStartupLocation.CenterOwner,
|
||||
ShowInTaskbar = false,
|
||||
Background = this.FindResource("SurfaceBrush") as IBrush,
|
||||
Content = new StackPanel
|
||||
{
|
||||
Spacing = 16,
|
||||
Margin = new Thickness(20),
|
||||
Children =
|
||||
{
|
||||
new TextBlock { Text = message, TextWrapping = TextWrapping.Wrap },
|
||||
new StackPanel
|
||||
{
|
||||
Orientation = Orientation.Horizontal,
|
||||
Spacing = 8,
|
||||
HorizontalAlignment = HorizontalAlignment.Right,
|
||||
Children = { cancel, confirm }
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
cancel.Click += (_, _) => { tcs.TrySetResult(false); dialog.Close(); };
|
||||
confirm.Click += (_, _) => { tcs.TrySetResult(true); dialog.Close(); };
|
||||
dialog.Closed += (_, _) => tcs.TrySetResult(false);
|
||||
|
||||
_ = dialog.ShowDialog(owner);
|
||||
return await tcs.Task;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -55,7 +55,6 @@ public partial class TasksIslandView : UserControl
|
||||
await modal.ShowDialog(owner);
|
||||
// ShowDialog completes once the window is closed (CloseAction or OS close).
|
||||
};
|
||||
vm.ConfirmAsync = ShowConfirmAsync;
|
||||
vm.SelectionChanged += (_, _) => ScrollSelectedIntoView();
|
||||
}
|
||||
};
|
||||
@@ -71,50 +70,6 @@ public partial class TasksIslandView : UserControl
|
||||
Dispatcher.UIThread.Post(() => RowsListBox.ScrollIntoView(target), DispatcherPriority.Background);
|
||||
}
|
||||
|
||||
private async System.Threading.Tasks.Task<bool> ShowConfirmAsync(string message)
|
||||
{
|
||||
var owner = TopLevel.GetTopLevel(this) as Window;
|
||||
if (owner is null) return false;
|
||||
|
||||
var tcs = new TaskCompletionSource<bool>();
|
||||
var cancel = new Button { Content = "Cancel", MinWidth = 90 };
|
||||
var confirm = new Button { Content = "Confirm", MinWidth = 90, Classes = { "danger" } };
|
||||
|
||||
var dialog = new Window
|
||||
{
|
||||
Title = "Confirm",
|
||||
Width = 380,
|
||||
SizeToContent = SizeToContent.Height,
|
||||
CanResize = false,
|
||||
WindowStartupLocation = WindowStartupLocation.CenterOwner,
|
||||
ShowInTaskbar = false,
|
||||
Background = this.FindResource("SurfaceBrush") as IBrush,
|
||||
Content = new StackPanel
|
||||
{
|
||||
Margin = new Thickness(20),
|
||||
Spacing = 16,
|
||||
Children =
|
||||
{
|
||||
new TextBlock { Text = message, TextWrapping = TextWrapping.Wrap },
|
||||
new StackPanel
|
||||
{
|
||||
Orientation = Orientation.Horizontal,
|
||||
HorizontalAlignment = HorizontalAlignment.Right,
|
||||
Spacing = 8,
|
||||
Children = { cancel, confirm },
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
cancel.Click += (_, _) => { tcs.TrySetResult(false); dialog.Close(); };
|
||||
confirm.Click += (_, _) => { tcs.TrySetResult(true); dialog.Close(); };
|
||||
dialog.Closed += (_, _) => tcs.TrySetResult(false);
|
||||
|
||||
_ = dialog.ShowDialog(owner);
|
||||
return await tcs.Task;
|
||||
}
|
||||
|
||||
// ── Custom ghost drag ────────────────────────────────────────────────────
|
||||
// Replaces both the OLE DoDragDropAsync reorder and the OLE drop-to-queue path: a hand-built
|
||||
// drag (pointer capture + a transparent topmost ghost window) is the only way to get a
|
||||
|
||||
@@ -8,6 +8,7 @@ using Avalonia.Layout;
|
||||
using Avalonia.Media;
|
||||
using Avalonia.Platform.Storage;
|
||||
using Avalonia.VisualTree;
|
||||
using ClaudeDo.Ui.Localization;
|
||||
using ClaudeDo.Ui.ViewModels;
|
||||
|
||||
namespace ClaudeDo.Ui.Views.MissionControl;
|
||||
@@ -73,20 +74,21 @@ public partial class MissionControlView : UserControl
|
||||
UpdateQueueColumn();
|
||||
}
|
||||
|
||||
// Abandon-run confirmation -- same TaskCompletionSource-backed plain Window as
|
||||
// TasksIslandView.ShowConfirmAsync (no shared control for this shape yet).
|
||||
// Abandon-run confirmation -- own plain-Window TaskCompletionSource dialog, not routed
|
||||
// through WindowDialogService: it's owned by the main window, so showing it while Mission
|
||||
// Control (a separate Window) is focused would put it behind Mission Control.
|
||||
private async Task<bool> ShowConfirmAsync(string message)
|
||||
{
|
||||
var owner = TopLevel.GetTopLevel(this) as Window;
|
||||
if (owner is null) return false;
|
||||
|
||||
var tcs = new TaskCompletionSource<bool>();
|
||||
var cancel = new Button { Content = "Cancel", MinWidth = 90 };
|
||||
var confirm = new Button { Content = "Confirm", MinWidth = 90, Classes = { "danger" } };
|
||||
var cancel = new Button { Content = Loc.T("dialog.cancel"), MinWidth = 90 };
|
||||
var confirm = new Button { Content = Loc.T("dialog.confirm"), MinWidth = 90, Classes = { "danger" } };
|
||||
|
||||
var dialog = new Window
|
||||
{
|
||||
Title = "Confirm",
|
||||
Title = Loc.T("dialog.confirmTitle"),
|
||||
Width = 380,
|
||||
SizeToContent = SizeToContent.Height,
|
||||
CanResize = false,
|
||||
|
||||
@@ -6,6 +6,7 @@ using Avalonia.Controls;
|
||||
using Avalonia.Controls.ApplicationLifetimes;
|
||||
using Avalonia.Layout;
|
||||
using Avalonia.Media;
|
||||
using ClaudeDo.Ui.Localization;
|
||||
using ClaudeDo.Ui.Services;
|
||||
using ClaudeDo.Ui.ViewModels;
|
||||
using ClaudeDo.Ui.ViewModels.Conflicts;
|
||||
@@ -71,7 +72,7 @@ public sealed class WindowDialogService : IDialogService
|
||||
|
||||
public async Task ShowSettingsAsync(SettingsModalViewModel vm)
|
||||
{
|
||||
vm.Worktrees.ConfirmAsync = ConfirmAsync;
|
||||
vm.Worktrees.ConfirmAsync = message => ConfirmAsync(message);
|
||||
var dlg = new SettingsModalView { DataContext = vm };
|
||||
vm.RequestRepoImport = () =>
|
||||
{
|
||||
@@ -90,7 +91,7 @@ public sealed class WindowDialogService : IDialogService
|
||||
{
|
||||
var dlg = new ListSettingsModalView { DataContext = vm };
|
||||
vm.CloseAction = () => dlg.Close();
|
||||
vm.ConfirmAsync = ConfirmAsync;
|
||||
vm.ConfirmAsync = message => ConfirmAsync(message);
|
||||
vm.ShowErrorAsync = ShowErrorAsync;
|
||||
await dlg.ShowDialog(_owner);
|
||||
}
|
||||
@@ -144,7 +145,7 @@ public sealed class WindowDialogService : IDialogService
|
||||
_diffViewerWindow = diffDlg;
|
||||
diffDlg.Show(_owner);
|
||||
};
|
||||
vm.ConfirmAction = ConfirmAsync;
|
||||
vm.ConfirmAction = message => ConfirmAsync(message);
|
||||
if (Shell is { } shell)
|
||||
{
|
||||
vm.ResolveMergeVm = shell.ResolveMergeVm;
|
||||
@@ -206,13 +207,13 @@ public sealed class WindowDialogService : IDialogService
|
||||
_cheatSheets.Activate();
|
||||
}
|
||||
|
||||
public Task<bool> ConfirmAsync(string message)
|
||||
public Task<bool> ConfirmAsync(string message, string? confirmLabel = null)
|
||||
{
|
||||
var tcs = new TaskCompletionSource<bool>();
|
||||
var cancel = new Button { Content = "Cancel", MinWidth = 90 };
|
||||
var confirm = new Button { Content = "Confirm", MinWidth = 90, Classes = { "danger" } };
|
||||
var cancel = new Button { Content = Loc.T("dialog.cancel"), MinWidth = 90 };
|
||||
var confirm = new Button { Content = confirmLabel ?? Loc.T("dialog.confirm"), MinWidth = 90, Classes = { "danger" } };
|
||||
|
||||
var dialog = NoticeWindow("Confirm", 380, message,
|
||||
var dialog = NoticeWindow(Loc.T("dialog.confirmTitle"), 380, message,
|
||||
new StackPanel
|
||||
{
|
||||
Orientation = Orientation.Horizontal,
|
||||
@@ -231,8 +232,8 @@ public sealed class WindowDialogService : IDialogService
|
||||
|
||||
public Task ShowErrorAsync(string message)
|
||||
{
|
||||
var ok = new Button { Content = "OK", MinWidth = 90 };
|
||||
var dialog = NoticeWindow("Error", 360, message,
|
||||
var ok = new Button { Content = Loc.T("dialog.ok"), MinWidth = 90 };
|
||||
var dialog = NoticeWindow(Loc.T("dialog.errorTitle"), 360, message,
|
||||
new StackPanel
|
||||
{
|
||||
Orientation = Orientation.Horizontal,
|
||||
|
||||
Reference in New Issue
Block a user