feat(installer): Config view — Save/Repair/Uninstall commands + footer buttons
This commit is contained in:
@@ -1,5 +1,6 @@
|
|||||||
using System.Windows;
|
using System.Windows;
|
||||||
using ClaudeDo.Installer.Core;
|
using ClaudeDo.Installer.Core;
|
||||||
|
using ClaudeDo.Installer.Steps;
|
||||||
using CommunityToolkit.Mvvm.ComponentModel;
|
using CommunityToolkit.Mvvm.ComponentModel;
|
||||||
using CommunityToolkit.Mvvm.Input;
|
using CommunityToolkit.Mvvm.Input;
|
||||||
|
|
||||||
@@ -8,6 +9,11 @@ namespace ClaudeDo.Installer.Views;
|
|||||||
public partial class SettingsViewModel : ObservableObject
|
public partial class SettingsViewModel : ObservableObject
|
||||||
{
|
{
|
||||||
private readonly InstallContext _context;
|
private readonly InstallContext _context;
|
||||||
|
private readonly IReleaseClient _releases;
|
||||||
|
private readonly StopServiceStep _stopService;
|
||||||
|
private readonly StartServiceStep _startService;
|
||||||
|
private readonly DownloadAndExtractStep _downloadStep;
|
||||||
|
private readonly UninstallRunner _uninstallRunner;
|
||||||
|
|
||||||
public IReadOnlyList<IInstallerPage> Pages { get; }
|
public IReadOnlyList<IInstallerPage> Pages { get; }
|
||||||
|
|
||||||
@@ -20,12 +26,29 @@ public partial class SettingsViewModel : ObservableObject
|
|||||||
[ObservableProperty]
|
[ObservableProperty]
|
||||||
private bool _isStatusError;
|
private bool _isStatusError;
|
||||||
|
|
||||||
public SettingsViewModel(PageResolver resolver, InstallContext context)
|
[ObservableProperty]
|
||||||
|
private string _versionLabel = "";
|
||||||
|
|
||||||
|
public SettingsViewModel(
|
||||||
|
PageResolver resolver,
|
||||||
|
InstallContext context,
|
||||||
|
IReleaseClient releases,
|
||||||
|
StopServiceStep stopService,
|
||||||
|
StartServiceStep startService,
|
||||||
|
DownloadAndExtractStep downloadStep,
|
||||||
|
UninstallRunner uninstallRunner)
|
||||||
{
|
{
|
||||||
Pages = resolver.SettingsPages;
|
Pages = resolver.SettingsPages;
|
||||||
_context = context;
|
_context = context;
|
||||||
|
_releases = releases;
|
||||||
|
_stopService = stopService;
|
||||||
|
_startService = startService;
|
||||||
|
_downloadStep = downloadStep;
|
||||||
|
_uninstallRunner = uninstallRunner;
|
||||||
_selectedPage = Pages.FirstOrDefault();
|
_selectedPage = Pages.FirstOrDefault();
|
||||||
|
|
||||||
|
VersionLabel = $"Installed: {context.InstalledVersion ?? "?"} Installer: {context.InstallerVersion ?? "?"}";
|
||||||
|
|
||||||
_ = LoadAllAsync();
|
_ = LoadAllAsync();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -36,9 +59,8 @@ public partial class SettingsViewModel : ObservableObject
|
|||||||
}
|
}
|
||||||
|
|
||||||
[RelayCommand]
|
[RelayCommand]
|
||||||
private async Task Apply()
|
private async Task Save()
|
||||||
{
|
{
|
||||||
// Validate all pages
|
|
||||||
foreach (var page in Pages)
|
foreach (var page in Pages)
|
||||||
{
|
{
|
||||||
if (!page.Validate())
|
if (!page.Validate())
|
||||||
@@ -50,11 +72,9 @@ public partial class SettingsViewModel : ObservableObject
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Apply all pages (writes to InstallContext)
|
|
||||||
foreach (var page in Pages)
|
foreach (var page in Pages)
|
||||||
await page.ApplyAsync();
|
await page.ApplyAsync();
|
||||||
|
|
||||||
// Write config files directly
|
|
||||||
var workerCfg = new InstallerWorkerConfig
|
var workerCfg = new InstallerWorkerConfig
|
||||||
{
|
{
|
||||||
DbPath = _context.DbPath,
|
DbPath = _context.DbPath,
|
||||||
@@ -75,13 +95,67 @@ public partial class SettingsViewModel : ObservableObject
|
|||||||
};
|
};
|
||||||
uiCfg.Save();
|
uiCfg.Save();
|
||||||
|
|
||||||
StatusMessage = "Settings saved successfully.";
|
StatusMessage = "Settings saved.";
|
||||||
IsStatusError = false;
|
IsStatusError = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
[RelayCommand]
|
[RelayCommand]
|
||||||
private void Close()
|
private async Task Repair()
|
||||||
{
|
{
|
||||||
|
var confirm = MessageBox.Show(
|
||||||
|
"Re-download and reinstall the ClaudeDo binaries? Your config and database are NOT affected.",
|
||||||
|
"Repair ClaudeDo",
|
||||||
|
MessageBoxButton.OKCancel,
|
||||||
|
MessageBoxImage.Question);
|
||||||
|
|
||||||
|
if (confirm != MessageBoxResult.OK) return;
|
||||||
|
|
||||||
|
StatusMessage = "Repairing...";
|
||||||
|
IsStatusError = false;
|
||||||
|
|
||||||
|
var progress = new Progress<string>(msg => StatusMessage = msg);
|
||||||
|
var steps = new IInstallStep[] { _stopService, _downloadStep, _startService };
|
||||||
|
|
||||||
|
foreach (var step in steps)
|
||||||
|
{
|
||||||
|
var r = await step.ExecuteAsync(_context, progress, CancellationToken.None);
|
||||||
|
if (!r.Success)
|
||||||
|
{
|
||||||
|
StatusMessage = $"{step.Name} failed: {r.ErrorMessage}";
|
||||||
|
IsStatusError = true;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
StatusMessage = "Repair complete.";
|
||||||
|
}
|
||||||
|
|
||||||
|
[RelayCommand]
|
||||||
|
private async Task Uninstall()
|
||||||
|
{
|
||||||
|
var confirm = MessageBox.Show(
|
||||||
|
"This will remove ClaudeDo AND delete all of your tasks, configuration, and database.\n\nContinue?",
|
||||||
|
"Uninstall ClaudeDo",
|
||||||
|
MessageBoxButton.YesNo,
|
||||||
|
MessageBoxImage.Warning);
|
||||||
|
|
||||||
|
if (confirm != MessageBoxResult.Yes) return;
|
||||||
|
|
||||||
|
var progress = new Progress<string>(msg => StatusMessage = msg);
|
||||||
|
var r = await _uninstallRunner.RunAsync(progress, CancellationToken.None);
|
||||||
|
|
||||||
|
if (!r.Success)
|
||||||
|
{
|
||||||
|
StatusMessage = $"Uninstall failed: {r.ErrorMessage}";
|
||||||
|
IsStatusError = true;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
MessageBox.Show("ClaudeDo has been removed.", "Uninstall complete",
|
||||||
|
MessageBoxButton.OK, MessageBoxImage.Information);
|
||||||
Application.Current.Shutdown();
|
Application.Current.Shutdown();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[RelayCommand]
|
||||||
|
private void Close() => Application.Current.Shutdown();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -61,31 +61,37 @@
|
|||||||
<ColumnDefinition Width="*"/>
|
<ColumnDefinition Width="*"/>
|
||||||
<ColumnDefinition Width="Auto"/>
|
<ColumnDefinition Width="Auto"/>
|
||||||
<ColumnDefinition Width="Auto"/>
|
<ColumnDefinition Width="Auto"/>
|
||||||
|
<ColumnDefinition Width="Auto"/>
|
||||||
|
<ColumnDefinition Width="Auto"/>
|
||||||
|
<ColumnDefinition Width="Auto"/>
|
||||||
</Grid.ColumnDefinitions>
|
</Grid.ColumnDefinitions>
|
||||||
|
|
||||||
<!-- Status message -->
|
<!-- Status message / version label -->
|
||||||
<TextBlock Grid.Column="0" Text="{Binding StatusMessage}"
|
<StackPanel Grid.Column="0" VerticalAlignment="Center">
|
||||||
VerticalAlignment="Center" FontSize="12">
|
<TextBlock Text="{Binding VersionLabel}" FontSize="11" Opacity="0.7"/>
|
||||||
<TextBlock.Style>
|
<TextBlock Text="{Binding StatusMessage}" FontSize="12">
|
||||||
<Style TargetType="TextBlock">
|
<TextBlock.Style>
|
||||||
<Setter Property="Foreground" Value="{StaticResource AccentBrush}"/>
|
<Style TargetType="TextBlock">
|
||||||
<Style.Triggers>
|
<Setter Property="Foreground" Value="{StaticResource AccentBrush}"/>
|
||||||
<DataTrigger Binding="{Binding IsStatusError}" Value="True">
|
<Style.Triggers>
|
||||||
<Setter Property="Foreground" Value="{StaticResource ErrorBrush}"/>
|
<DataTrigger Binding="{Binding IsStatusError}" Value="True">
|
||||||
</DataTrigger>
|
<Setter Property="Foreground" Value="{StaticResource ErrorBrush}"/>
|
||||||
</Style.Triggers>
|
</DataTrigger>
|
||||||
</Style>
|
</Style.Triggers>
|
||||||
</TextBlock.Style>
|
</Style>
|
||||||
</TextBlock>
|
</TextBlock.Style>
|
||||||
|
</TextBlock>
|
||||||
|
</StackPanel>
|
||||||
|
|
||||||
<Button Grid.Column="1" Content="Close"
|
<Button Grid.Column="1" Content="Uninstall" Margin="0,0,8,0"
|
||||||
Command="{Binding CloseCommand}"
|
Command="{Binding UninstallCommand}"/>
|
||||||
Margin="0,0,8,0" MinWidth="80"/>
|
<Button Grid.Column="2" Content="Repair" Margin="0,0,8,0"
|
||||||
|
Command="{Binding RepairCommand}"/>
|
||||||
<Button Grid.Column="2" Content="Save & Apply"
|
<Button Grid.Column="3" Content="Save" Margin="0,0,8,0"
|
||||||
Command="{Binding ApplyCommand}"
|
Command="{Binding SaveCommand}"
|
||||||
Style="{StaticResource AccentButton}"
|
Style="{StaticResource AccentButton}"/>
|
||||||
MinWidth="100"/>
|
<Button Grid.Column="4" Content="Close"
|
||||||
|
Command="{Binding CloseCommand}"/>
|
||||||
</Grid>
|
</Grid>
|
||||||
</Border>
|
</Border>
|
||||||
</Grid>
|
</Grid>
|
||||||
|
|||||||
Reference in New Issue
Block a user