fix(installer): make user-data deletion on uninstall opt-in
Add bool removeAppData parameter (default false) to UninstallRunner.RunAsync, gate ~/.todo-app deletion on it, surface a checkbox in SettingsWindow, and update the confirmation message to reflect whether data will be removed. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -17,7 +17,7 @@ public sealed class UninstallRunner
|
||||
_stopService = stopService;
|
||||
}
|
||||
|
||||
public async Task<StepResult> RunAsync(IProgress<string> progress, CancellationToken ct)
|
||||
public async Task<StepResult> RunAsync(bool removeAppData, IProgress<string> progress, CancellationToken ct)
|
||||
{
|
||||
// 1) Validate install dir up front — refuse obviously unsafe paths.
|
||||
// Prevents Directory.Delete(recursive:true) from wiping C:\ or C:\Program Files\.
|
||||
@@ -67,13 +67,16 @@ public sealed class UninstallRunner
|
||||
failures.Add($"install dir ({_context.InstallDirectory}): {err}");
|
||||
}
|
||||
|
||||
// 6) Delete ~/.todo-app (config + DB + logs) — user opted into full removal.
|
||||
var appData = Paths.AppDataRoot();
|
||||
if (Directory.Exists(appData))
|
||||
// 6) Delete ~/.todo-app (config + DB + logs) — only if user opted in.
|
||||
if (removeAppData)
|
||||
{
|
||||
progress.Report($"Deleting {appData}...");
|
||||
if (!TryDeleteDir(appData, out var err))
|
||||
failures.Add($"app data ({appData}): {err}");
|
||||
var appData = Paths.AppDataRoot();
|
||||
if (Directory.Exists(appData))
|
||||
{
|
||||
progress.Report($"Deleting {appData}...");
|
||||
if (!TryDeleteDir(appData, out var err))
|
||||
failures.Add($"app data ({appData}): {err}");
|
||||
}
|
||||
}
|
||||
|
||||
// 7) If we were launched from inside the install dir (Apps & Features case),
|
||||
|
||||
@@ -29,6 +29,9 @@ public partial class SettingsViewModel : ObservableObject
|
||||
[ObservableProperty]
|
||||
private string _versionLabel = "";
|
||||
|
||||
[ObservableProperty]
|
||||
private bool _removeAppData;
|
||||
|
||||
public SettingsViewModel(
|
||||
PageResolver resolver,
|
||||
InstallContext context,
|
||||
@@ -133,8 +136,12 @@ public partial class SettingsViewModel : ObservableObject
|
||||
[RelayCommand]
|
||||
private async Task Uninstall()
|
||||
{
|
||||
var dataNote = RemoveAppData
|
||||
? "This will remove ClaudeDo AND delete all of your tasks, configuration, and database.\n\nContinue?"
|
||||
: "This will remove ClaudeDo. Your tasks, configuration, and database in ~/.todo-app will be kept.\n\nContinue?";
|
||||
|
||||
var confirm = MessageBox.Show(
|
||||
"This will remove ClaudeDo AND delete all of your tasks, configuration, and database.\n\nContinue?",
|
||||
dataNote,
|
||||
"Uninstall ClaudeDo",
|
||||
MessageBoxButton.YesNo,
|
||||
MessageBoxImage.Warning);
|
||||
@@ -142,7 +149,7 @@ public partial class SettingsViewModel : ObservableObject
|
||||
if (confirm != MessageBoxResult.Yes) return;
|
||||
|
||||
var progress = new Progress<string>(msg => StatusMessage = msg);
|
||||
var r = await _uninstallRunner.RunAsync(progress, CancellationToken.None);
|
||||
var r = await _uninstallRunner.RunAsync(RemoveAppData, progress, CancellationToken.None);
|
||||
|
||||
if (!r.Success)
|
||||
{
|
||||
|
||||
@@ -69,6 +69,7 @@
|
||||
<ColumnDefinition Width="Auto"/>
|
||||
<ColumnDefinition Width="Auto"/>
|
||||
<ColumnDefinition Width="Auto"/>
|
||||
<ColumnDefinition Width="Auto"/>
|
||||
</Grid.ColumnDefinitions>
|
||||
|
||||
<!-- Status message / version label -->
|
||||
@@ -88,14 +89,17 @@
|
||||
</TextBlock>
|
||||
</StackPanel>
|
||||
|
||||
<Button Grid.Column="1" Content="Uninstall" Margin="0,0,8,0"
|
||||
<CheckBox Grid.Column="1" IsChecked="{Binding RemoveAppData}"
|
||||
Content="Remove user data (tasks, logs, configs in ~/.todo-app)"
|
||||
Margin="0,0,12,0" VerticalAlignment="Center"/>
|
||||
<Button Grid.Column="2" Content="Uninstall" Margin="0,0,8,0"
|
||||
Command="{Binding UninstallCommand}"/>
|
||||
<Button Grid.Column="2" Content="Repair" Margin="0,0,8,0"
|
||||
<Button Grid.Column="3" Content="Repair" Margin="0,0,8,0"
|
||||
Command="{Binding RepairCommand}"/>
|
||||
<Button Grid.Column="3" Content="Save" Margin="0,0,8,0"
|
||||
<Button Grid.Column="4" Content="Save" Margin="0,0,8,0"
|
||||
Command="{Binding SaveCommand}"
|
||||
Style="{StaticResource AccentButton}"/>
|
||||
<Button Grid.Column="4" Content="Close"
|
||||
<Button Grid.Column="5" Content="Close"
|
||||
Command="{Binding CloseCommand}"/>
|
||||
</Grid>
|
||||
</Border>
|
||||
|
||||
Reference in New Issue
Block a user