feat(installer): rewrite WelcomePage for download-mode + update heading

Removes SourceDirectory field (no longer in InstallContext), adds
dynamic Heading/Subheading/InstallDirEditable for FreshInstall vs Update
mode, and updates XAML to match sibling page style.
This commit is contained in:
Mika Kuns
2026-04-15 10:14:38 +02:00
parent 5e432a4a27
commit da1fe2109a
2 changed files with 38 additions and 73 deletions

View File

@@ -9,40 +9,29 @@
<ScrollViewer VerticalScrollBarVisibility="Auto"> <ScrollViewer VerticalScrollBarVisibility="Auto">
<StackPanel MaxWidth="520"> <StackPanel MaxWidth="520">
<TextBlock Text="Welcome to ClaudeDo Setup" FontSize="20" FontWeight="SemiBold"
Margin="0,0,0,6"/>
<TextBlock Text="This wizard will build, configure, and install ClaudeDo on your machine."
Foreground="{StaticResource TextSecondaryBrush}" Margin="0,0,0,24"
TextWrapping="Wrap"/>
<!-- Source Directory --> <TextBlock Text="{Binding Heading}" FontSize="20" FontWeight="SemiBold" Margin="0,0,0,6"/>
<Label Content="Source Directory"/> <TextBlock Text="{Binding Subheading}" TextWrapping="Wrap"
<Grid Margin="0,0,0,4"> Foreground="{StaticResource TextSecondaryBrush}" Margin="0,0,0,24"/>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<TextBox Grid.Column="0" Text="{Binding SourceDirectory, UpdateSourceTrigger=PropertyChanged}"/>
<Button Grid.Column="1" Content="Browse..." Command="{Binding BrowseSourceCommand}"
Margin="8,0,0,0"/>
</Grid>
<TextBlock Text="{Binding SourceError}" Foreground="{StaticResource ErrorBrush}" FontSize="11"
Visibility="{Binding SourceError, Converter={StaticResource NullToCollapsedConverter}}"
Margin="0,0,0,16"/>
<!-- Install Directory -->
<Label Content="Install Directory"/> <Label Content="Install Directory"/>
<Grid Margin="0,0,0,4"> <Grid Margin="0,0,0,4">
<Grid.ColumnDefinitions> <Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/> <ColumnDefinition Width="*"/>
<ColumnDefinition Width="Auto"/> <ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions> </Grid.ColumnDefinitions>
<TextBox Grid.Column="0" Text="{Binding InstallDirectory, UpdateSourceTrigger=PropertyChanged}"/> <TextBox Grid.Column="0"
<Button Grid.Column="1" Content="Browse..." Command="{Binding BrowseInstallCommand}" Text="{Binding InstallDirectory, UpdateSourceTrigger=PropertyChanged}"
Margin="8,0,0,0"/> IsEnabled="{Binding InstallDirEditable}"/>
<Button Grid.Column="1"
Content="Browse..."
Margin="8,0,0,0"
Command="{Binding BrowseInstallCommand}"
IsEnabled="{Binding InstallDirEditable}"/>
</Grid> </Grid>
<TextBlock Text="{Binding InstallError}" Foreground="{StaticResource ErrorBrush}" FontSize="11" <TextBlock Text="{Binding InstallError}" Foreground="{StaticResource ErrorBrush}" FontSize="11"
Visibility="{Binding InstallError, Converter={StaticResource NullToCollapsedConverter}}"/> Visibility="{Binding InstallError, Converter={StaticResource NullToCollapsedConverter}}"/>
</StackPanel> </StackPanel>
</ScrollViewer> </ScrollViewer>
</UserControl> </UserControl>

View File

@@ -19,88 +19,64 @@ public partial class WelcomePageViewModel : ObservableObject, IInstallerPage
public bool ShowInSettings => false; public bool ShowInSettings => false;
public UserControl View => _view ??= new WelcomePageView { DataContext = this }; public UserControl View => _view ??= new WelcomePageView { DataContext = this };
[ObservableProperty] private string _sourceDirectory = "";
[ObservableProperty] private string _installDirectory = @"C:\Program Files\ClaudeDo"; [ObservableProperty] private string _installDirectory = @"C:\Program Files\ClaudeDo";
[ObservableProperty] private string? _sourceError;
[ObservableProperty] private string? _installError; [ObservableProperty] private string? _installError;
[ObservableProperty] private string _heading = "Install ClaudeDo";
[ObservableProperty] private string _subheading = "Set the installation directory and continue.";
[ObservableProperty] private bool _installDirEditable = true;
public WelcomePageViewModel(InstallContext context) public WelcomePageViewModel(InstallContext context)
{ {
_context = context; _context = context;
_sourceDirectory = DetectSourceDirectory();
} }
public Task LoadAsync() public Task LoadAsync()
{ {
if (!string.IsNullOrEmpty(_context.SourceDirectory)) InstallDirectory = string.IsNullOrEmpty(_context.InstallDirectory)
SourceDirectory = _context.SourceDirectory; ? @"C:\Program Files\ClaudeDo"
if (!string.IsNullOrEmpty(_context.InstallDirectory)) : _context.InstallDirectory;
InstallDirectory = _context.InstallDirectory;
switch (_context.Mode)
{
case InstallerMode.FreshInstall:
Heading = "Install ClaudeDo";
Subheading = "Choose where to install ClaudeDo, then click Next.";
InstallDirEditable = true;
break;
case InstallerMode.Update:
Heading = $"Update ClaudeDo {_context.InstalledVersion} -> {_context.LatestVersion}";
Subheading = "Your tasks, config, and database will be preserved. Click Next to continue.";
InstallDirEditable = false;
break;
}
return Task.CompletedTask; return Task.CompletedTask;
} }
public Task ApplyAsync() public Task ApplyAsync()
{ {
_context.SourceDirectory = SourceDirectory;
_context.InstallDirectory = InstallDirectory; _context.InstallDirectory = InstallDirectory;
return Task.CompletedTask; return Task.CompletedTask;
} }
public bool Validate() public bool Validate()
{ {
var valid = true;
if (string.IsNullOrWhiteSpace(SourceDirectory) ||
!File.Exists(Path.Combine(SourceDirectory, "ClaudeDo.slnx")))
{
SourceError = "Source directory must contain ClaudeDo.slnx";
valid = false;
}
else
{
SourceError = null;
}
if (string.IsNullOrWhiteSpace(InstallDirectory)) if (string.IsNullOrWhiteSpace(InstallDirectory))
{ {
InstallError = "Install directory is required"; InstallError = "Install directory is required";
valid = false; return false;
} }
else InstallError = null;
{ return true;
InstallError = null;
}
return valid;
}
[RelayCommand]
private void BrowseSource()
{
var dialog = new OpenFolderDialog { Title = "Select ClaudeDo source directory" };
if (dialog.ShowDialog() == true)
SourceDirectory = dialog.FolderName;
} }
[RelayCommand] [RelayCommand]
private void BrowseInstall() private void BrowseInstall()
{ {
if (!InstallDirEditable) return;
var dialog = new OpenFolderDialog { Title = "Select installation directory" }; var dialog = new OpenFolderDialog { Title = "Select installation directory" };
if (dialog.ShowDialog() == true) if (dialog.ShowDialog() == true)
InstallDirectory = dialog.FolderName; InstallDirectory = dialog.FolderName;
} }
private static string DetectSourceDirectory()
{
var dir = AppContext.BaseDirectory;
for (var i = 0; i < 8; i++)
{
if (File.Exists(Path.Combine(dir, "ClaudeDo.slnx")))
return dir;
var parent = Directory.GetParent(dir)?.FullName;
if (parent is null) break;
dir = parent;
}
return "";
}
} }