feat(i18n): localize installer with language picker and config write-through
- Init Localizer at app startup (before self-update prompt) and assign to TrExtension.Localizer - Register ILocalizer in DI; inject into WizardViewModel and SettingsViewModel - WizardViewModel: SelectedLanguage ComboBox binding with OnSelectedLanguageChanged -> SetLanguage + InstallContext.Language - WizardWindow.xaml: DockPanel wraps step chips + language ComboBox (right-aligned) - Localize all installer XAML: WizardWindow, WelcomePage, PathsPage, ServicePage, UiSettingsPage, InstallPage, SettingsWindow, SelfUpdatePromptWindow - Localize page Title properties and WizardViewModel.NextButtonText via TrExtension.Localizer - Persist chosen Language in WriteConfigStep and SettingsViewModel.Save into ui.config.json - Append installer section to en.json (nav, welcome, paths, service, uiSettings, install, settings, selfUpdate) Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -1,7 +1,12 @@
|
|||||||
|
using System.Globalization;
|
||||||
|
using System.IO;
|
||||||
|
using System.Linq;
|
||||||
using System.Net.Http;
|
using System.Net.Http;
|
||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
using System.Windows;
|
using System.Windows;
|
||||||
using ClaudeDo.Installer.Core;
|
using ClaudeDo.Installer.Core;
|
||||||
|
using ClaudeDo.Installer.Localization;
|
||||||
|
using ClaudeDo.Localization;
|
||||||
using ClaudeDo.Releases;
|
using ClaudeDo.Releases;
|
||||||
using ClaudeDo.Installer.Pages.InstallPage;
|
using ClaudeDo.Installer.Pages.InstallPage;
|
||||||
using ClaudeDo.Installer.Pages.PathsPage;
|
using ClaudeDo.Installer.Pages.PathsPage;
|
||||||
@@ -22,6 +27,17 @@ public partial class App : Application
|
|||||||
{
|
{
|
||||||
base.OnStartup(e);
|
base.OnStartup(e);
|
||||||
|
|
||||||
|
// --- Initialize localizer as early as possible so all windows can use {loc:Tr} ---
|
||||||
|
var localesDir = Path.Combine(AppContext.BaseDirectory, "locales");
|
||||||
|
var localeStore = LocaleStore.Load(localesDir);
|
||||||
|
var existingSettings = InstallerAppSettings.Load();
|
||||||
|
var initialLang = !string.IsNullOrWhiteSpace(existingSettings.Language)
|
||||||
|
? existingSettings.Language
|
||||||
|
: CultureResolver.Resolve(CultureInfo.CurrentUICulture.Name,
|
||||||
|
localeStore.Available.Select(l => l.Code).ToArray(), "en");
|
||||||
|
var localizer = new Localizer(localeStore, initialLang);
|
||||||
|
TrExtension.Localizer = localizer;
|
||||||
|
|
||||||
// --- Self-update pre-flight ---
|
// --- Self-update pre-flight ---
|
||||||
// Resolve current exe path. Assembly.Location may point to a .dll for apphost-based
|
// Resolve current exe path. Assembly.Location may point to a .dll for apphost-based
|
||||||
// .NET apps; swap to the .exe companion when that happens.
|
// .NET apps; swap to the .exe companion when that happens.
|
||||||
@@ -120,7 +136,7 @@ public partial class App : Application
|
|||||||
|
|
||||||
// --- Existing wizard start-up unchanged below this line ---
|
// --- Existing wizard start-up unchanged below this line ---
|
||||||
|
|
||||||
_services = BuildServices();
|
_services = BuildServices(localizer);
|
||||||
|
|
||||||
var context = _services.GetRequiredService<InstallContext>();
|
var context = _services.GetRequiredService<InstallContext>();
|
||||||
context.InstallerVersion = GetInstallerVersion();
|
context.InstallerVersion = GetInstallerVersion();
|
||||||
@@ -183,9 +199,10 @@ public partial class App : Application
|
|||||||
return infoAttr?.InformationalVersion ?? "0.0.0";
|
return infoAttr?.InformationalVersion ?? "0.0.0";
|
||||||
}
|
}
|
||||||
|
|
||||||
private static ServiceProvider BuildServices()
|
private static ServiceProvider BuildServices(ILocalizer localizer)
|
||||||
{
|
{
|
||||||
var sc = new ServiceCollection();
|
var sc = new ServiceCollection();
|
||||||
|
sc.AddSingleton(localizer);
|
||||||
|
|
||||||
// Core
|
// Core
|
||||||
sc.AddSingleton<InstallContext>();
|
sc.AddSingleton<InstallContext>();
|
||||||
|
|||||||
@@ -36,4 +36,7 @@ public sealed class InstallContext
|
|||||||
// WelcomePage — register the external MCP endpoint with the Claude CLI.
|
// WelcomePage — register the external MCP endpoint with the Claude CLI.
|
||||||
public bool RegisterMcpWithClaude { get; set; } = true;
|
public bool RegisterMcpWithClaude { get; set; } = true;
|
||||||
public int ExternalMcpPort { get; set; } = 47_822;
|
public int ExternalMcpPort { get; set; } = 47_822;
|
||||||
|
|
||||||
|
// Language selection (persisted to ui.config.json)
|
||||||
|
public string Language { get; set; } = "";
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||||
xmlns:local="clr-namespace:ClaudeDo.Installer.Pages.InstallPage"
|
xmlns:local="clr-namespace:ClaudeDo.Installer.Pages.InstallPage"
|
||||||
|
xmlns:loc="clr-namespace:ClaudeDo.Installer.Localization"
|
||||||
d:DataContext="{d:DesignInstance local:InstallPageViewModel}"
|
d:DataContext="{d:DesignInstance local:InstallPageViewModel}"
|
||||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||||
@@ -17,8 +18,8 @@
|
|||||||
|
|
||||||
<!-- Header -->
|
<!-- Header -->
|
||||||
<StackPanel Grid.Row="0" Margin="0,0,0,16">
|
<StackPanel Grid.Row="0" Margin="0,0,0,16">
|
||||||
<TextBlock Text="Installation" FontSize="18" FontWeight="SemiBold" Margin="0,0,0,4"/>
|
<TextBlock Text="{loc:Tr installer.install.title}" FontSize="18" FontWeight="SemiBold" Margin="0,0,0,4"/>
|
||||||
<TextBlock Text="Click Install to build and deploy ClaudeDo."
|
<TextBlock Text="{loc:Tr installer.install.subtitle}"
|
||||||
Foreground="{StaticResource TextSecondaryBrush}" TextWrapping="Wrap"/>
|
Foreground="{StaticResource TextSecondaryBrush}" TextWrapping="Wrap"/>
|
||||||
</StackPanel>
|
</StackPanel>
|
||||||
|
|
||||||
@@ -89,11 +90,11 @@
|
|||||||
|
|
||||||
<!-- Action buttons -->
|
<!-- Action buttons -->
|
||||||
<StackPanel Grid.Row="3" Orientation="Horizontal" HorizontalAlignment="Right" Margin="0,12,0,0">
|
<StackPanel Grid.Row="3" Orientation="Horizontal" HorizontalAlignment="Right" Margin="0,12,0,0">
|
||||||
<Button Content="Cancel" Command="{Binding CancelInstallCommand}"
|
<Button Content="{loc:Tr installer.nav.cancel}" Command="{Binding CancelInstallCommand}"
|
||||||
Visibility="{Binding IsInstalling, Converter={StaticResource BoolToVisConverter}}"
|
Visibility="{Binding IsInstalling, Converter={StaticResource BoolToVisConverter}}"
|
||||||
Margin="0,0,8,0"/>
|
Margin="0,0,8,0"/>
|
||||||
|
|
||||||
<Button Content="Launch ClaudeDo" Command="{Binding LaunchAppCommand}"
|
<Button Content="{loc:Tr installer.install.launch}" Command="{Binding LaunchAppCommand}"
|
||||||
Style="{StaticResource AccentButton}"
|
Style="{StaticResource AccentButton}"
|
||||||
Visibility="{Binding IsComplete, Converter={StaticResource BoolToVisConverter}}"/>
|
Visibility="{Binding IsComplete, Converter={StaticResource BoolToVisConverter}}"/>
|
||||||
</StackPanel>
|
</StackPanel>
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ using System.Diagnostics;
|
|||||||
using System.Windows;
|
using System.Windows;
|
||||||
using System.Windows.Controls;
|
using System.Windows.Controls;
|
||||||
using ClaudeDo.Installer.Core;
|
using ClaudeDo.Installer.Core;
|
||||||
|
using ClaudeDo.Installer.Localization;
|
||||||
using ClaudeDo.Installer.Steps;
|
using ClaudeDo.Installer.Steps;
|
||||||
using CommunityToolkit.Mvvm.ComponentModel;
|
using CommunityToolkit.Mvvm.ComponentModel;
|
||||||
using CommunityToolkit.Mvvm.Input;
|
using CommunityToolkit.Mvvm.Input;
|
||||||
@@ -29,7 +30,7 @@ public partial class InstallPageViewModel : ObservableObject, IInstallerPage
|
|||||||
private InstallPageView? _view;
|
private InstallPageView? _view;
|
||||||
private CancellationTokenSource? _cts;
|
private CancellationTokenSource? _cts;
|
||||||
|
|
||||||
public string Title => "Install";
|
public string Title => TrExtension.Localizer?["installer.install.title"] ?? "Install";
|
||||||
public string Icon => "\uE896";
|
public string Icon => "\uE896";
|
||||||
public int Order => 99;
|
public int Order => 99;
|
||||||
public bool ShowInWizard => true;
|
public bool ShowInWizard => true;
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||||
xmlns:local="clr-namespace:ClaudeDo.Installer.Pages.PathsPage"
|
xmlns:local="clr-namespace:ClaudeDo.Installer.Pages.PathsPage"
|
||||||
|
xmlns:loc="clr-namespace:ClaudeDo.Installer.Localization"
|
||||||
d:DataContext="{d:DesignInstance local:PathsPageViewModel}"
|
d:DataContext="{d:DesignInstance local:PathsPageViewModel}"
|
||||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||||
@@ -9,28 +10,28 @@
|
|||||||
|
|
||||||
<ScrollViewer VerticalScrollBarVisibility="Auto">
|
<ScrollViewer VerticalScrollBarVisibility="Auto">
|
||||||
<StackPanel MaxWidth="520">
|
<StackPanel MaxWidth="520">
|
||||||
<TextBlock Text="Data Paths" FontSize="18" FontWeight="SemiBold" Margin="0,0,0,4"/>
|
<TextBlock Text="{loc:Tr installer.paths.title}" FontSize="18" FontWeight="SemiBold" Margin="0,0,0,4"/>
|
||||||
<TextBlock Text="Configure where ClaudeDo stores its data."
|
<TextBlock Text="{loc:Tr installer.paths.subtitle}"
|
||||||
Foreground="{StaticResource TextSecondaryBrush}" Margin="0,0,0,20"
|
Foreground="{StaticResource TextSecondaryBrush}" Margin="0,0,0,20"
|
||||||
TextWrapping="Wrap"/>
|
TextWrapping="Wrap"/>
|
||||||
|
|
||||||
<Label Content="Database Path"/>
|
<Label Content="{loc:Tr installer.paths.databasePath}"/>
|
||||||
<TextBox Text="{Binding DbPath, UpdateSourceTrigger=PropertyChanged}" Margin="0,0,0,12"/>
|
<TextBox Text="{Binding DbPath, UpdateSourceTrigger=PropertyChanged}" Margin="0,0,0,12"/>
|
||||||
|
|
||||||
<Label Content="Log Directory"/>
|
<Label Content="{loc:Tr installer.paths.logDirectory}"/>
|
||||||
<TextBox Text="{Binding LogRoot, UpdateSourceTrigger=PropertyChanged}" Margin="0,0,0,12"/>
|
<TextBox Text="{Binding LogRoot, UpdateSourceTrigger=PropertyChanged}" Margin="0,0,0,12"/>
|
||||||
|
|
||||||
<Label Content="Sandbox Root"/>
|
<Label Content="{loc:Tr installer.paths.sandboxRoot}"/>
|
||||||
<TextBox Text="{Binding SandboxRoot, UpdateSourceTrigger=PropertyChanged}" Margin="0,0,0,12"/>
|
<TextBox Text="{Binding SandboxRoot, UpdateSourceTrigger=PropertyChanged}" Margin="0,0,0,12"/>
|
||||||
|
|
||||||
<Label Content="Worktree Strategy"/>
|
<Label Content="{loc:Tr installer.paths.worktreeStrategy}"/>
|
||||||
<ComboBox SelectedItem="{Binding WorktreeRootStrategy}" Margin="0,0,0,12">
|
<ComboBox SelectedItem="{Binding WorktreeRootStrategy}" Margin="0,0,0,12">
|
||||||
<sys:String xmlns:sys="clr-namespace:System;assembly=mscorlib">sibling</sys:String>
|
<sys:String xmlns:sys="clr-namespace:System;assembly=mscorlib">sibling</sys:String>
|
||||||
<sys:String xmlns:sys="clr-namespace:System;assembly=mscorlib">central</sys:String>
|
<sys:String xmlns:sys="clr-namespace:System;assembly=mscorlib">central</sys:String>
|
||||||
</ComboBox>
|
</ComboBox>
|
||||||
|
|
||||||
<StackPanel Visibility="{Binding IsCentralVisible, Converter={StaticResource BoolToVisConverter}}">
|
<StackPanel Visibility="{Binding IsCentralVisible, Converter={StaticResource BoolToVisConverter}}">
|
||||||
<Label Content="Central Worktree Root"/>
|
<Label Content="{loc:Tr installer.paths.centralWorktreeRoot}"/>
|
||||||
<TextBox Text="{Binding CentralWorktreeRoot, UpdateSourceTrigger=PropertyChanged}" Margin="0,0,0,12"/>
|
<TextBox Text="{Binding CentralWorktreeRoot, UpdateSourceTrigger=PropertyChanged}" Margin="0,0,0,12"/>
|
||||||
</StackPanel>
|
</StackPanel>
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
using System.Windows.Controls;
|
using System.Windows.Controls;
|
||||||
using ClaudeDo.Installer.Core;
|
using ClaudeDo.Installer.Core;
|
||||||
|
using ClaudeDo.Installer.Localization;
|
||||||
using CommunityToolkit.Mvvm.ComponentModel;
|
using CommunityToolkit.Mvvm.ComponentModel;
|
||||||
|
|
||||||
namespace ClaudeDo.Installer.Pages.PathsPage;
|
namespace ClaudeDo.Installer.Pages.PathsPage;
|
||||||
@@ -9,7 +10,7 @@ public partial class PathsPageViewModel : ObservableObject, IInstallerPage
|
|||||||
private readonly InstallContext _context;
|
private readonly InstallContext _context;
|
||||||
private PathsPageView? _view;
|
private PathsPageView? _view;
|
||||||
|
|
||||||
public string Title => "Paths";
|
public string Title => TrExtension.Localizer?["installer.paths.title"] ?? "Paths";
|
||||||
public string Icon => "\uE8B7";
|
public string Icon => "\uE8B7";
|
||||||
public int Order => 1;
|
public int Order => 1;
|
||||||
public bool ShowInWizard => true;
|
public bool ShowInWizard => true;
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||||
xmlns:local="clr-namespace:ClaudeDo.Installer.Pages.ServicePage"
|
xmlns:local="clr-namespace:ClaudeDo.Installer.Pages.ServicePage"
|
||||||
|
xmlns:loc="clr-namespace:ClaudeDo.Installer.Localization"
|
||||||
d:DataContext="{d:DesignInstance local:ServicePageViewModel}"
|
d:DataContext="{d:DesignInstance local:ServicePageViewModel}"
|
||||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||||
@@ -9,37 +10,37 @@
|
|||||||
|
|
||||||
<ScrollViewer VerticalScrollBarVisibility="Auto">
|
<ScrollViewer VerticalScrollBarVisibility="Auto">
|
||||||
<StackPanel MaxWidth="520">
|
<StackPanel MaxWidth="520">
|
||||||
<TextBlock Text="Worker" FontSize="18" FontWeight="SemiBold" Margin="0,0,0,4"/>
|
<TextBlock Text="{loc:Tr installer.service.title}" FontSize="18" FontWeight="SemiBold" Margin="0,0,0,4"/>
|
||||||
<TextBlock Text="Configure the ClaudeDo background worker."
|
<TextBlock Text="{loc:Tr installer.service.subtitle}"
|
||||||
Foreground="{StaticResource TextSecondaryBrush}" Margin="0,0,0,20"
|
Foreground="{StaticResource TextSecondaryBrush}" Margin="0,0,0,20"
|
||||||
TextWrapping="Wrap"/>
|
TextWrapping="Wrap"/>
|
||||||
|
|
||||||
<Label Content="SignalR Port"/>
|
<Label Content="{loc:Tr installer.service.signalRPort}"/>
|
||||||
<TextBox Text="{Binding SignalRPort, UpdateSourceTrigger=PropertyChanged}" Margin="0,0,0,12"/>
|
<TextBox Text="{Binding SignalRPort, UpdateSourceTrigger=PropertyChanged}" Margin="0,0,0,12"/>
|
||||||
|
|
||||||
<Label Content="Queue Backstop Interval (ms)"/>
|
<Label Content="{loc:Tr installer.service.queueBackstopInterval}"/>
|
||||||
<TextBox Text="{Binding QueueBackstopIntervalMs, UpdateSourceTrigger=PropertyChanged}" Margin="0,0,0,12"/>
|
<TextBox Text="{Binding QueueBackstopIntervalMs, UpdateSourceTrigger=PropertyChanged}" Margin="0,0,0,12"/>
|
||||||
|
|
||||||
<Label Content="Claude CLI Path"/>
|
<Label Content="{loc:Tr installer.service.claudeCliPath}"/>
|
||||||
<Grid Margin="0,0,0,12">
|
<Grid Margin="0,0,0,12">
|
||||||
<Grid.ColumnDefinitions>
|
<Grid.ColumnDefinitions>
|
||||||
<ColumnDefinition Width="*"/>
|
<ColumnDefinition Width="*"/>
|
||||||
<ColumnDefinition Width="Auto"/>
|
<ColumnDefinition Width="Auto"/>
|
||||||
</Grid.ColumnDefinitions>
|
</Grid.ColumnDefinitions>
|
||||||
<TextBox Grid.Column="0" Text="{Binding ClaudeBin, UpdateSourceTrigger=PropertyChanged}"/>
|
<TextBox Grid.Column="0" Text="{Binding ClaudeBin, UpdateSourceTrigger=PropertyChanged}"/>
|
||||||
<Button Grid.Column="1" Content="Browse..." Command="{Binding BrowseClaudeCommand}"
|
<Button Grid.Column="1" Content="{loc:Tr installer.nav.browse}" Command="{Binding BrowseClaudeCommand}"
|
||||||
Margin="8,0,0,0"/>
|
Margin="8,0,0,0"/>
|
||||||
</Grid>
|
</Grid>
|
||||||
|
|
||||||
<Separator Margin="0,4,0,12"/>
|
<Separator Margin="0,4,0,12"/>
|
||||||
|
|
||||||
<TextBlock Text="The worker runs as you (the logged-in user) via a per-user logon task, so it can use your Claude CLI authentication."
|
<TextBlock Text="{loc:Tr installer.service.autostartHint}"
|
||||||
Foreground="{StaticResource TextDimBrush}" FontSize="11" Margin="0,0,0,12"
|
Foreground="{StaticResource TextDimBrush}" FontSize="11" Margin="0,0,0,12"
|
||||||
TextWrapping="Wrap"/>
|
TextWrapping="Wrap"/>
|
||||||
|
|
||||||
<CheckBox Content="Start worker automatically at logon" IsChecked="{Binding AutoStart}" Margin="0,0,0,12"/>
|
<CheckBox Content="{loc:Tr installer.service.autostart}" IsChecked="{Binding AutoStart}" Margin="0,0,0,12"/>
|
||||||
|
|
||||||
<Label Content="Restart Delay (ms)"/>
|
<Label Content="{loc:Tr installer.service.restartDelay}"/>
|
||||||
<TextBox Text="{Binding RestartDelayMs, UpdateSourceTrigger=PropertyChanged}" Margin="0,0,0,12"/>
|
<TextBox Text="{Binding RestartDelayMs, UpdateSourceTrigger=PropertyChanged}" Margin="0,0,0,12"/>
|
||||||
|
|
||||||
<TextBlock Text="{Binding ValidationError}" Foreground="{StaticResource ErrorBrush}" FontSize="11"
|
<TextBlock Text="{Binding ValidationError}" Foreground="{StaticResource ErrorBrush}" FontSize="11"
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
using System.Windows.Controls;
|
using System.Windows.Controls;
|
||||||
using ClaudeDo.Installer.Core;
|
using ClaudeDo.Installer.Core;
|
||||||
|
using ClaudeDo.Installer.Localization;
|
||||||
using CommunityToolkit.Mvvm.ComponentModel;
|
using CommunityToolkit.Mvvm.ComponentModel;
|
||||||
using CommunityToolkit.Mvvm.Input;
|
using CommunityToolkit.Mvvm.Input;
|
||||||
using Microsoft.Win32;
|
using Microsoft.Win32;
|
||||||
@@ -11,7 +12,7 @@ public partial class ServicePageViewModel : ObservableObject, IInstallerPage
|
|||||||
private readonly InstallContext _context;
|
private readonly InstallContext _context;
|
||||||
private ServicePageView? _view;
|
private ServicePageView? _view;
|
||||||
|
|
||||||
public string Title => "Service";
|
public string Title => TrExtension.Localizer?["installer.service.title"] ?? "Service";
|
||||||
public string Icon => "\uE912";
|
public string Icon => "\uE912";
|
||||||
public int Order => 2;
|
public int Order => 2;
|
||||||
public bool ShowInWizard => true;
|
public bool ShowInWizard => true;
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||||
xmlns:local="clr-namespace:ClaudeDo.Installer.Pages.UiSettingsPage"
|
xmlns:local="clr-namespace:ClaudeDo.Installer.Pages.UiSettingsPage"
|
||||||
|
xmlns:loc="clr-namespace:ClaudeDo.Installer.Localization"
|
||||||
d:DataContext="{d:DesignInstance local:UiSettingsPageViewModel}"
|
d:DataContext="{d:DesignInstance local:UiSettingsPageViewModel}"
|
||||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||||
@@ -9,22 +10,22 @@
|
|||||||
|
|
||||||
<ScrollViewer VerticalScrollBarVisibility="Auto">
|
<ScrollViewer VerticalScrollBarVisibility="Auto">
|
||||||
<StackPanel MaxWidth="520">
|
<StackPanel MaxWidth="520">
|
||||||
<TextBlock Text="UI Settings" FontSize="18" FontWeight="SemiBold" Margin="0,0,0,4"/>
|
<TextBlock Text="{loc:Tr installer.uiSettings.title}" FontSize="18" FontWeight="SemiBold" Margin="0,0,0,4"/>
|
||||||
<TextBlock Text="Configure the ClaudeDo desktop UI connection settings."
|
<TextBlock Text="{loc:Tr installer.uiSettings.subtitle}"
|
||||||
Foreground="{StaticResource TextSecondaryBrush}" Margin="0,0,0,20"
|
Foreground="{StaticResource TextSecondaryBrush}" Margin="0,0,0,20"
|
||||||
TextWrapping="Wrap"/>
|
TextWrapping="Wrap"/>
|
||||||
|
|
||||||
<CheckBox Content="Sync with service settings" IsChecked="{Binding IsSynced}" Margin="0,0,0,16"/>
|
<CheckBox Content="{loc:Tr installer.uiSettings.syncWithService}" IsChecked="{Binding IsSynced}" Margin="0,0,0,16"/>
|
||||||
|
|
||||||
<Label Content="SignalR URL"/>
|
<Label Content="{loc:Tr installer.uiSettings.signalRUrl}"/>
|
||||||
<TextBox Text="{Binding SignalRUrl, UpdateSourceTrigger=PropertyChanged}"
|
<TextBox Text="{Binding SignalRUrl, UpdateSourceTrigger=PropertyChanged}"
|
||||||
IsReadOnly="{Binding IsSynced}" Margin="0,0,0,12"/>
|
IsReadOnly="{Binding IsSynced}" Margin="0,0,0,12"/>
|
||||||
|
|
||||||
<Label Content="Database Path"/>
|
<Label Content="{loc:Tr installer.paths.databasePath}"/>
|
||||||
<TextBox Text="{Binding UiDbPath, UpdateSourceTrigger=PropertyChanged}"
|
<TextBox Text="{Binding UiDbPath, UpdateSourceTrigger=PropertyChanged}"
|
||||||
IsReadOnly="{Binding IsSynced}" Margin="0,0,0,12"/>
|
IsReadOnly="{Binding IsSynced}" Margin="0,0,0,12"/>
|
||||||
|
|
||||||
<TextBlock Text="When synced, these values are derived from the Service and Paths pages."
|
<TextBlock Text="{loc:Tr installer.uiSettings.syncHint}"
|
||||||
Foreground="{StaticResource TextDimBrush}" FontSize="11" TextWrapping="Wrap"
|
Foreground="{StaticResource TextDimBrush}" FontSize="11" TextWrapping="Wrap"
|
||||||
Visibility="{Binding IsSynced, Converter={StaticResource BoolToVisConverter}}"
|
Visibility="{Binding IsSynced, Converter={StaticResource BoolToVisConverter}}"
|
||||||
Margin="0,0,0,12"/>
|
Margin="0,0,0,12"/>
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
using System.Windows.Controls;
|
using System.Windows.Controls;
|
||||||
using ClaudeDo.Installer.Core;
|
using ClaudeDo.Installer.Core;
|
||||||
|
using ClaudeDo.Installer.Localization;
|
||||||
using CommunityToolkit.Mvvm.ComponentModel;
|
using CommunityToolkit.Mvvm.ComponentModel;
|
||||||
|
|
||||||
namespace ClaudeDo.Installer.Pages.UiSettingsPage;
|
namespace ClaudeDo.Installer.Pages.UiSettingsPage;
|
||||||
@@ -9,7 +10,7 @@ public partial class UiSettingsPageViewModel : ObservableObject, IInstallerPage
|
|||||||
private readonly InstallContext _context;
|
private readonly InstallContext _context;
|
||||||
private UiSettingsPageView? _view;
|
private UiSettingsPageView? _view;
|
||||||
|
|
||||||
public string Title => "UI Settings";
|
public string Title => TrExtension.Localizer?["installer.uiSettings.title"] ?? "UI Settings";
|
||||||
public string Icon => "\uE771";
|
public string Icon => "\uE771";
|
||||||
public int Order => 3;
|
public int Order => 3;
|
||||||
public bool ShowInWizard => true;
|
public bool ShowInWizard => true;
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||||
xmlns:local="clr-namespace:ClaudeDo.Installer.Pages.WelcomePage"
|
xmlns:local="clr-namespace:ClaudeDo.Installer.Pages.WelcomePage"
|
||||||
|
xmlns:loc="clr-namespace:ClaudeDo.Installer.Localization"
|
||||||
d:DataContext="{d:DesignInstance local:WelcomePageViewModel}"
|
d:DataContext="{d:DesignInstance local:WelcomePageViewModel}"
|
||||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||||
@@ -14,7 +15,7 @@
|
|||||||
<TextBlock Text="{Binding Subheading}" TextWrapping="Wrap"
|
<TextBlock Text="{Binding Subheading}" TextWrapping="Wrap"
|
||||||
Foreground="{StaticResource TextSecondaryBrush}" Margin="0,0,0,24"/>
|
Foreground="{StaticResource TextSecondaryBrush}" Margin="0,0,0,24"/>
|
||||||
|
|
||||||
<Label Content="Install Directory"/>
|
<Label Content="{loc:Tr installer.welcome.installDirectory}"/>
|
||||||
<Grid Margin="0,0,0,4">
|
<Grid Margin="0,0,0,4">
|
||||||
<Grid.ColumnDefinitions>
|
<Grid.ColumnDefinitions>
|
||||||
<ColumnDefinition Width="*"/>
|
<ColumnDefinition Width="*"/>
|
||||||
@@ -24,7 +25,7 @@
|
|||||||
Text="{Binding InstallDirectory, UpdateSourceTrigger=PropertyChanged}"
|
Text="{Binding InstallDirectory, UpdateSourceTrigger=PropertyChanged}"
|
||||||
IsEnabled="{Binding InstallDirEditable}"/>
|
IsEnabled="{Binding InstallDirEditable}"/>
|
||||||
<Button Grid.Column="1"
|
<Button Grid.Column="1"
|
||||||
Content="Browse..."
|
Content="{loc:Tr installer.nav.browse}"
|
||||||
Margin="8,0,0,0"
|
Margin="8,0,0,0"
|
||||||
Command="{Binding BrowseInstallCommand}"
|
Command="{Binding BrowseInstallCommand}"
|
||||||
IsEnabled="{Binding InstallDirEditable}"/>
|
IsEnabled="{Binding InstallDirEditable}"/>
|
||||||
@@ -32,10 +33,10 @@
|
|||||||
<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}}"/>
|
||||||
|
|
||||||
<CheckBox Content="Register MCP server with Claude"
|
<CheckBox Content="{loc:Tr installer.welcome.registerMcp}"
|
||||||
IsChecked="{Binding RegisterMcp}"
|
IsChecked="{Binding RegisterMcp}"
|
||||||
Margin="0,24,0,0"/>
|
Margin="0,24,0,0"/>
|
||||||
<TextBlock Text="Runs 'claude mcp add' so Claude can view and manage your ClaudeDo tasks. You can change this later."
|
<TextBlock Text="{loc:Tr installer.welcome.registerMcpHint}"
|
||||||
TextWrapping="Wrap" FontSize="11"
|
TextWrapping="Wrap" FontSize="11"
|
||||||
Foreground="{StaticResource TextSecondaryBrush}"
|
Foreground="{StaticResource TextSecondaryBrush}"
|
||||||
Margin="0,4,0,0"/>
|
Margin="0,4,0,0"/>
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Windows.Controls;
|
using System.Windows.Controls;
|
||||||
using ClaudeDo.Installer.Core;
|
using ClaudeDo.Installer.Core;
|
||||||
|
using ClaudeDo.Installer.Localization;
|
||||||
using CommunityToolkit.Mvvm.ComponentModel;
|
using CommunityToolkit.Mvvm.ComponentModel;
|
||||||
using CommunityToolkit.Mvvm.Input;
|
using CommunityToolkit.Mvvm.Input;
|
||||||
using Microsoft.Win32;
|
using Microsoft.Win32;
|
||||||
@@ -12,7 +13,7 @@ public partial class WelcomePageViewModel : ObservableObject, IInstallerPage
|
|||||||
private readonly InstallContext _context;
|
private readonly InstallContext _context;
|
||||||
private WelcomePageView? _view;
|
private WelcomePageView? _view;
|
||||||
|
|
||||||
public string Title => "Welcome";
|
public string Title => TrExtension.Localizer?["installer.welcome.title"] ?? "Welcome";
|
||||||
public string Icon => "\uE80F";
|
public string Icon => "\uE80F";
|
||||||
public int Order => 0;
|
public int Order => 0;
|
||||||
public bool ShowInWizard => true;
|
public bool ShowInWizard => true;
|
||||||
@@ -37,17 +38,18 @@ public partial class WelcomePageViewModel : ObservableObject, IInstallerPage
|
|||||||
? @"C:\Program Files\ClaudeDo"
|
? @"C:\Program Files\ClaudeDo"
|
||||||
: _context.InstallDirectory;
|
: _context.InstallDirectory;
|
||||||
|
|
||||||
|
var loc = TrExtension.Localizer;
|
||||||
switch (_context.Mode)
|
switch (_context.Mode)
|
||||||
{
|
{
|
||||||
case InstallerMode.FreshInstall:
|
case InstallerMode.FreshInstall:
|
||||||
Heading = "Install ClaudeDo";
|
Heading = loc?["installer.welcome.heading"] ?? "Install ClaudeDo";
|
||||||
Subheading = "Choose where to install ClaudeDo, then click Next.";
|
Subheading = loc?["installer.welcome.subheading"] ?? "Choose where to install ClaudeDo, then click Next.";
|
||||||
InstallDirEditable = true;
|
InstallDirEditable = true;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case InstallerMode.Update:
|
case InstallerMode.Update:
|
||||||
Heading = $"Update ClaudeDo {_context.InstalledVersion ?? "?"} -> {_context.LatestVersion ?? "?"}";
|
Heading = $"Update ClaudeDo {_context.InstalledVersion ?? "?"} -> {_context.LatestVersion ?? "?"}";
|
||||||
Subheading = "Your tasks, config, and database will be preserved. Click Next to continue.";
|
Subheading = loc?["installer.welcome.updateSubheading"] ?? "Your tasks, config, and database will be preserved. Click Next to continue.";
|
||||||
InstallDirEditable = false; // stay where we were installed
|
InstallDirEditable = false; // stay where we were installed
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
|||||||
@@ -31,6 +31,7 @@ public sealed class WriteConfigStep : IInstallStep
|
|||||||
{
|
{
|
||||||
DbPath = Paths.Expand(ctx.UiDbPath),
|
DbPath = Paths.Expand(ctx.UiDbPath),
|
||||||
SignalRUrl = ctx.SignalRUrl,
|
SignalRUrl = ctx.SignalRUrl,
|
||||||
|
Language = ctx.Language,
|
||||||
};
|
};
|
||||||
uiCfg.Save();
|
uiCfg.Save();
|
||||||
progress.Report("Written ui.config.json");
|
progress.Report("Written ui.config.json");
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
<Window x:Class="ClaudeDo.Installer.Views.SelfUpdatePromptWindow"
|
<Window x:Class="ClaudeDo.Installer.Views.SelfUpdatePromptWindow"
|
||||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||||
|
xmlns:loc="clr-namespace:ClaudeDo.Installer.Localization"
|
||||||
Title="ClaudeDo Installer Update"
|
Title="ClaudeDo Installer Update"
|
||||||
Width="460" Height="200"
|
Width="460" Height="200"
|
||||||
WindowStartupLocation="CenterScreen"
|
WindowStartupLocation="CenterScreen"
|
||||||
@@ -13,13 +14,13 @@
|
|||||||
<RowDefinition Height="*"/>
|
<RowDefinition Height="*"/>
|
||||||
<RowDefinition Height="Auto"/>
|
<RowDefinition Height="Auto"/>
|
||||||
</Grid.RowDefinitions>
|
</Grid.RowDefinitions>
|
||||||
<TextBlock Grid.Row="0" FontSize="16" FontWeight="SemiBold" Text="A newer installer is available"/>
|
<TextBlock Grid.Row="0" FontSize="16" FontWeight="SemiBold" Text="{loc:Tr installer.selfUpdate.heading}"/>
|
||||||
<TextBlock Grid.Row="1" Margin="0,8,0,0" TextWrapping="Wrap" x:Name="DetailText"/>
|
<TextBlock Grid.Row="1" Margin="0,8,0,0" TextWrapping="Wrap" x:Name="DetailText"/>
|
||||||
<TextBlock Grid.Row="2" Margin="0,12,0,0" TextWrapping="Wrap" Foreground="#a0a0a0" x:Name="ProgressText" Visibility="Collapsed"/>
|
<TextBlock Grid.Row="2" Margin="0,12,0,0" TextWrapping="Wrap" Foreground="#a0a0a0" x:Name="ProgressText" Visibility="Collapsed"/>
|
||||||
<StackPanel Grid.Row="3" Orientation="Horizontal" HorizontalAlignment="Right">
|
<StackPanel Grid.Row="3" Orientation="Horizontal" HorizontalAlignment="Right">
|
||||||
<Button x:Name="UpdateBtn" Content="Update" MinWidth="90" Margin="4,0" Padding="10,4" Click="UpdateBtn_Click" IsDefault="True"/>
|
<Button x:Name="UpdateBtn" Content="{loc:Tr installer.selfUpdate.update}" MinWidth="90" Margin="4,0" Padding="10,4" Click="UpdateBtn_Click" IsDefault="True"/>
|
||||||
<Button x:Name="ContinueBtn" Content="Continue anyway" MinWidth="140" Margin="4,0" Padding="10,4" Click="ContinueBtn_Click"/>
|
<Button x:Name="ContinueBtn" Content="{loc:Tr installer.selfUpdate.continueAnyway}" MinWidth="140" Margin="4,0" Padding="10,4" Click="ContinueBtn_Click"/>
|
||||||
<Button x:Name="CancelBtn" Content="Cancel" MinWidth="90" Margin="4,0" Padding="10,4" Click="CancelBtn_Click" IsCancel="True"/>
|
<Button x:Name="CancelBtn" Content="{loc:Tr installer.nav.cancel}" MinWidth="90" Margin="4,0" Padding="10,4" Click="CancelBtn_Click" IsCancel="True"/>
|
||||||
</StackPanel>
|
</StackPanel>
|
||||||
</Grid>
|
</Grid>
|
||||||
</Window>
|
</Window>
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
using System.Windows;
|
using System.Windows;
|
||||||
using ClaudeDo.Installer.Core;
|
using ClaudeDo.Installer.Core;
|
||||||
|
using ClaudeDo.Localization;
|
||||||
using ClaudeDo.Releases;
|
using ClaudeDo.Releases;
|
||||||
using ClaudeDo.Installer.Steps;
|
using ClaudeDo.Installer.Steps;
|
||||||
using CommunityToolkit.Mvvm.ComponentModel;
|
using CommunityToolkit.Mvvm.ComponentModel;
|
||||||
@@ -10,6 +11,7 @@ namespace ClaudeDo.Installer.Views;
|
|||||||
public partial class SettingsViewModel : ObservableObject
|
public partial class SettingsViewModel : ObservableObject
|
||||||
{
|
{
|
||||||
private readonly InstallContext _context;
|
private readonly InstallContext _context;
|
||||||
|
private readonly ILocalizer _localizer;
|
||||||
private readonly IReleaseClient _releases;
|
private readonly IReleaseClient _releases;
|
||||||
private readonly StopWorkerStep _stopService;
|
private readonly StopWorkerStep _stopService;
|
||||||
private readonly StartWorkerStep _startService;
|
private readonly StartWorkerStep _startService;
|
||||||
@@ -37,6 +39,7 @@ public partial class SettingsViewModel : ObservableObject
|
|||||||
public SettingsViewModel(
|
public SettingsViewModel(
|
||||||
PageResolver resolver,
|
PageResolver resolver,
|
||||||
InstallContext context,
|
InstallContext context,
|
||||||
|
ILocalizer localizer,
|
||||||
IReleaseClient releases,
|
IReleaseClient releases,
|
||||||
StopWorkerStep stopService,
|
StopWorkerStep stopService,
|
||||||
StartWorkerStep startService,
|
StartWorkerStep startService,
|
||||||
@@ -46,6 +49,7 @@ public partial class SettingsViewModel : ObservableObject
|
|||||||
{
|
{
|
||||||
Pages = resolver.SettingsPages;
|
Pages = resolver.SettingsPages;
|
||||||
_context = context;
|
_context = context;
|
||||||
|
_localizer = localizer;
|
||||||
_releases = releases;
|
_releases = releases;
|
||||||
_stopService = stopService;
|
_stopService = stopService;
|
||||||
_startService = startService;
|
_startService = startService;
|
||||||
@@ -104,6 +108,7 @@ public partial class SettingsViewModel : ObservableObject
|
|||||||
{
|
{
|
||||||
DbPath = _context.UiDbPath,
|
DbPath = _context.UiDbPath,
|
||||||
SignalRUrl = _context.SignalRUrl,
|
SignalRUrl = _context.SignalRUrl,
|
||||||
|
Language = _localizer.CurrentCode,
|
||||||
};
|
};
|
||||||
uiCfg.Save();
|
uiCfg.Save();
|
||||||
|
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||||
xmlns:views="clr-namespace:ClaudeDo.Installer.Views"
|
xmlns:views="clr-namespace:ClaudeDo.Installer.Views"
|
||||||
|
xmlns:loc="clr-namespace:ClaudeDo.Installer.Localization"
|
||||||
Title="ClaudeDo Settings"
|
Title="ClaudeDo Settings"
|
||||||
Icon="/ClaudeTaskSetup.ico"
|
Icon="/ClaudeTaskSetup.ico"
|
||||||
Width="720" Height="520"
|
Width="720" Height="520"
|
||||||
@@ -90,16 +91,16 @@
|
|||||||
</StackPanel>
|
</StackPanel>
|
||||||
|
|
||||||
<CheckBox Grid.Column="1" IsChecked="{Binding RemoveAppData}"
|
<CheckBox Grid.Column="1" IsChecked="{Binding RemoveAppData}"
|
||||||
Content="Remove user data (tasks, logs, configs in ~/.todo-app)"
|
Content="{loc:Tr installer.settings.removeUserData}"
|
||||||
Margin="0,0,12,0" VerticalAlignment="Center"/>
|
Margin="0,0,12,0" VerticalAlignment="Center"/>
|
||||||
<Button Grid.Column="2" Content="Uninstall" Margin="0,0,8,0"
|
<Button Grid.Column="2" Content="{loc:Tr installer.settings.uninstall}" Margin="0,0,8,0"
|
||||||
Command="{Binding UninstallCommand}"/>
|
Command="{Binding UninstallCommand}"/>
|
||||||
<Button Grid.Column="3" Content="Repair" Margin="0,0,8,0"
|
<Button Grid.Column="3" Content="{loc:Tr installer.settings.repair}" Margin="0,0,8,0"
|
||||||
Command="{Binding RepairCommand}"/>
|
Command="{Binding RepairCommand}"/>
|
||||||
<Button Grid.Column="4" Content="Save" Margin="0,0,8,0"
|
<Button Grid.Column="4" Content="{loc:Tr installer.settings.save}" Margin="0,0,8,0"
|
||||||
Command="{Binding SaveCommand}"
|
Command="{Binding SaveCommand}"
|
||||||
Style="{StaticResource AccentButton}"/>
|
Style="{StaticResource AccentButton}"/>
|
||||||
<Button Grid.Column="5" Content="Close"
|
<Button Grid.Column="5" Content="{loc:Tr installer.settings.close}"
|
||||||
Command="{Binding CloseCommand}"/>
|
Command="{Binding CloseCommand}"/>
|
||||||
</Grid>
|
</Grid>
|
||||||
</Border>
|
</Border>
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ using System.Windows;
|
|||||||
using ClaudeDo.Installer.Core;
|
using ClaudeDo.Installer.Core;
|
||||||
using ClaudeDo.Installer.Pages.InstallPage;
|
using ClaudeDo.Installer.Pages.InstallPage;
|
||||||
using ClaudeDo.Installer.Pages.WelcomePage;
|
using ClaudeDo.Installer.Pages.WelcomePage;
|
||||||
|
using ClaudeDo.Localization;
|
||||||
using CommunityToolkit.Mvvm.ComponentModel;
|
using CommunityToolkit.Mvvm.ComponentModel;
|
||||||
using CommunityToolkit.Mvvm.Input;
|
using CommunityToolkit.Mvvm.Input;
|
||||||
|
|
||||||
@@ -11,8 +12,20 @@ namespace ClaudeDo.Installer.Views;
|
|||||||
public partial class WizardViewModel : ObservableObject
|
public partial class WizardViewModel : ObservableObject
|
||||||
{
|
{
|
||||||
private readonly InstallContext _context;
|
private readonly InstallContext _context;
|
||||||
|
private readonly ILocalizer _localizer;
|
||||||
|
|
||||||
public IReadOnlyList<IInstallerPage> Pages { get; }
|
public IReadOnlyList<IInstallerPage> Pages { get; }
|
||||||
|
public IReadOnlyList<LanguageOption> Languages { get; }
|
||||||
|
|
||||||
|
[ObservableProperty]
|
||||||
|
private LanguageOption? _selectedLanguage;
|
||||||
|
|
||||||
|
partial void OnSelectedLanguageChanged(LanguageOption? value)
|
||||||
|
{
|
||||||
|
if (value is null) return;
|
||||||
|
_localizer.SetLanguage(value.Value.Code);
|
||||||
|
_context.Language = value.Value.Code;
|
||||||
|
}
|
||||||
|
|
||||||
[ObservableProperty]
|
[ObservableProperty]
|
||||||
[NotifyPropertyChangedFor(nameof(CanGoBack))]
|
[NotifyPropertyChangedFor(nameof(CanGoBack))]
|
||||||
@@ -24,14 +37,20 @@ public partial class WizardViewModel : ObservableObject
|
|||||||
public IInstallerPage CurrentPage => Pages[CurrentPageIndex];
|
public IInstallerPage CurrentPage => Pages[CurrentPageIndex];
|
||||||
public bool CanGoBack => CurrentPageIndex > 0;
|
public bool CanGoBack => CurrentPageIndex > 0;
|
||||||
public bool IsLastPage => CurrentPageIndex == Pages.Count - 1;
|
public bool IsLastPage => CurrentPageIndex == Pages.Count - 1;
|
||||||
public string NextButtonText => IsLastPage ? "Install" : "Next \u2192";
|
public string NextButtonText => IsLastPage
|
||||||
|
? (_localizer["installer.nav.install"])
|
||||||
|
: (_localizer["installer.nav.next"]);
|
||||||
|
|
||||||
[ObservableProperty]
|
[ObservableProperty]
|
||||||
private string? _validationError;
|
private string? _validationError;
|
||||||
|
|
||||||
public WizardViewModel(PageResolver resolver, InstallContext context)
|
public WizardViewModel(PageResolver resolver, InstallContext context, ILocalizer localizer)
|
||||||
{
|
{
|
||||||
_context = context;
|
_context = context;
|
||||||
|
_localizer = localizer;
|
||||||
|
Languages = localizer.AvailableLanguages;
|
||||||
|
_selectedLanguage = Languages.FirstOrDefault(l => l.Code == localizer.CurrentCode);
|
||||||
|
_context.Language = localizer.CurrentCode;
|
||||||
|
|
||||||
var all = resolver.WizardPages;
|
var all = resolver.WizardPages;
|
||||||
Pages = context.Mode == InstallerMode.Update
|
Pages = context.Mode == InstallerMode.Update
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||||
xmlns:views="clr-namespace:ClaudeDo.Installer.Views"
|
xmlns:views="clr-namespace:ClaudeDo.Installer.Views"
|
||||||
|
xmlns:loc="clr-namespace:ClaudeDo.Installer.Localization"
|
||||||
Title="ClaudeDo Installer"
|
Title="ClaudeDo Installer"
|
||||||
Icon="/ClaudeTaskSetup.ico"
|
Icon="/ClaudeTaskSetup.ico"
|
||||||
Width="720" Height="520"
|
Width="720" Height="520"
|
||||||
@@ -27,6 +28,12 @@
|
|||||||
<Border Grid.Row="0" Background="{StaticResource IslandBgBrush}"
|
<Border Grid.Row="0" Background="{StaticResource IslandBgBrush}"
|
||||||
BorderBrush="{StaticResource BorderSubtleBrush}" BorderThickness="0,0,0,1"
|
BorderBrush="{StaticResource BorderSubtleBrush}" BorderThickness="0,0,0,1"
|
||||||
Padding="20,14">
|
Padding="20,14">
|
||||||
|
<DockPanel>
|
||||||
|
<ComboBox DockPanel.Dock="Right"
|
||||||
|
ItemsSource="{Binding Languages}"
|
||||||
|
SelectedItem="{Binding SelectedLanguage, Mode=TwoWay}"
|
||||||
|
DisplayMemberPath="Name"
|
||||||
|
Width="150" HorizontalAlignment="Right" VerticalAlignment="Center"/>
|
||||||
<ItemsControl ItemsSource="{Binding Pages}">
|
<ItemsControl ItemsSource="{Binding Pages}">
|
||||||
<ItemsControl.ItemsPanel>
|
<ItemsControl.ItemsPanel>
|
||||||
<ItemsPanelTemplate>
|
<ItemsPanelTemplate>
|
||||||
@@ -61,6 +68,7 @@
|
|||||||
</DataTemplate>
|
</DataTemplate>
|
||||||
</ItemsControl.ItemTemplate>
|
</ItemsControl.ItemTemplate>
|
||||||
</ItemsControl>
|
</ItemsControl>
|
||||||
|
</DockPanel>
|
||||||
</Border>
|
</Border>
|
||||||
|
|
||||||
<!-- Page Content -->
|
<!-- Page Content -->
|
||||||
@@ -85,7 +93,7 @@
|
|||||||
VerticalAlignment="Center" FontSize="12"
|
VerticalAlignment="Center" FontSize="12"
|
||||||
Visibility="{Binding ValidationError, Converter={StaticResource NullToCollapsedConverter}}"/>
|
Visibility="{Binding ValidationError, Converter={StaticResource NullToCollapsedConverter}}"/>
|
||||||
|
|
||||||
<Button Grid.Column="1" Content="Back"
|
<Button Grid.Column="1" Content="{loc:Tr installer.nav.back}"
|
||||||
Command="{Binding GoBackCommand}"
|
Command="{Binding GoBackCommand}"
|
||||||
IsEnabled="{Binding CanGoBack}"
|
IsEnabled="{Binding CanGoBack}"
|
||||||
Margin="0,0,8,0" MinWidth="80"/>
|
Margin="0,0,8,0" MinWidth="80"/>
|
||||||
|
|||||||
@@ -262,6 +262,67 @@
|
|||||||
"emptyStateHint": "No report for this range yet. Click “Generate”."
|
"emptyStateHint": "No report for this range yet. Click “Generate”."
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"installer": {
|
||||||
|
"nav": {
|
||||||
|
"back": "Back",
|
||||||
|
"next": "Next →",
|
||||||
|
"install": "Install",
|
||||||
|
"browse": "Browse...",
|
||||||
|
"cancel": "Cancel"
|
||||||
|
},
|
||||||
|
"welcome": {
|
||||||
|
"title": "Welcome",
|
||||||
|
"heading": "Install ClaudeDo",
|
||||||
|
"subheading": "Choose where to install ClaudeDo, then click Next.",
|
||||||
|
"updateSubheading": "Your tasks, config, and database will be preserved. Click Next to continue.",
|
||||||
|
"installDirectory": "Install Directory",
|
||||||
|
"registerMcp": "Register MCP server with Claude",
|
||||||
|
"registerMcpHint": "Runs 'claude mcp add' so Claude can view and manage your ClaudeDo tasks. You can change this later."
|
||||||
|
},
|
||||||
|
"paths": {
|
||||||
|
"title": "Data Paths",
|
||||||
|
"subtitle": "Configure where ClaudeDo stores its data.",
|
||||||
|
"databasePath": "Database Path",
|
||||||
|
"logDirectory": "Log Directory",
|
||||||
|
"sandboxRoot": "Sandbox Root",
|
||||||
|
"worktreeStrategy": "Worktree Strategy",
|
||||||
|
"centralWorktreeRoot": "Central Worktree Root"
|
||||||
|
},
|
||||||
|
"service": {
|
||||||
|
"title": "Worker",
|
||||||
|
"subtitle": "Configure the ClaudeDo background worker.",
|
||||||
|
"signalRPort": "SignalR Port",
|
||||||
|
"queueBackstopInterval": "Queue Backstop Interval (ms)",
|
||||||
|
"claudeCliPath": "Claude CLI Path",
|
||||||
|
"autostart": "Start worker automatically at logon",
|
||||||
|
"autostartHint": "The worker runs as you (the logged-in user) via a per-user logon task, so it can use your Claude CLI authentication.",
|
||||||
|
"restartDelay": "Restart Delay (ms)"
|
||||||
|
},
|
||||||
|
"uiSettings": {
|
||||||
|
"title": "UI Settings",
|
||||||
|
"subtitle": "Configure the ClaudeDo desktop UI connection settings.",
|
||||||
|
"syncWithService": "Sync with service settings",
|
||||||
|
"signalRUrl": "SignalR URL",
|
||||||
|
"syncHint": "When synced, these values are derived from the Service and Paths pages."
|
||||||
|
},
|
||||||
|
"install": {
|
||||||
|
"title": "Installation",
|
||||||
|
"subtitle": "Click Install to build and deploy ClaudeDo.",
|
||||||
|
"launch": "Launch ClaudeDo"
|
||||||
|
},
|
||||||
|
"settings": {
|
||||||
|
"removeUserData": "Remove user data (tasks, logs, configs in ~/.todo-app)",
|
||||||
|
"uninstall": "Uninstall",
|
||||||
|
"repair": "Repair",
|
||||||
|
"save": "Save",
|
||||||
|
"close": "Close"
|
||||||
|
},
|
||||||
|
"selfUpdate": {
|
||||||
|
"heading": "A newer installer is available",
|
||||||
|
"update": "Update",
|
||||||
|
"continueAnyway": "Continue anyway"
|
||||||
|
}
|
||||||
|
},
|
||||||
"planning": {
|
"planning": {
|
||||||
"conflict": {
|
"conflict": {
|
||||||
"windowTitle": "Merge conflict",
|
"windowTitle": "Merge conflict",
|
||||||
|
|||||||
Reference in New Issue
Block a user