feat(app): step-by-step setup wizard instead of single-form panel

Startup now follows the blueprint §15 flow, one field per screen with
Avanti/Indietro: initial choice (open / create / restore), seed display
with write-it-down warning, seed confirmation by re-typing, mnemonic
validation on restore, optional BIP39 passphrase, and wallet file
password as the final step. Opening an encrypted file from the menu
routes to the same password step.
This commit is contained in:
2026-06-11 16:04:25 +02:00
parent 73a2d5356d
commit e8777fb458
2 changed files with 223 additions and 39 deletions
+94 -31
View File
@@ -31,44 +31,107 @@
</MenuItem>
</Menu>
<!-- ============ PANNELLO SETUP: crea / ripristina / apri ============ -->
<!-- ============ WIZARD DI SETUP (§15): un passo alla volta ============ -->
<ScrollViewer Grid.Row="1" IsVisible="{Binding IsSetupVisible}">
<StackPanel MaxWidth="560" Margin="24" Spacing="14">
<TextBlock Text="Palladium Wallet" FontSize="28" FontWeight="Bold"/>
<StackPanel MaxWidth="560" Margin="24,40" Spacing="18"
HorizontalAlignment="Center">
<TextBlock Text="Palladium Wallet" FontSize="28" FontWeight="Bold"
HorizontalAlignment="Center"/>
<StackPanel Orientation="Horizontal" Spacing="10">
<TextBlock Text="Rete:" VerticalAlignment="Center"/>
<ComboBox ItemsSource="{Binding Networks}"
SelectedItem="{Binding SelectedNetwork}"
MinWidth="140"/>
<!-- Passo 1: scelta iniziale -->
<StackPanel IsVisible="{Binding IsStepStart}" Spacing="12">
<StackPanel Orientation="Horizontal" Spacing="10" HorizontalAlignment="Center">
<TextBlock Text="Rete:" VerticalAlignment="Center"/>
<ComboBox ItemsSource="{Binding Networks}"
SelectedItem="{Binding SelectedNetwork}" MinWidth="140"/>
</StackPanel>
<Button Content="Apri il wallet esistente" FontSize="16"
HorizontalAlignment="Stretch" HorizontalContentAlignment="Center"
IsVisible="{Binding WalletFileExists}"
Command="{Binding WizardStartOpenCommand}"/>
<Button Content="Crea un nuovo wallet" FontSize="16"
HorizontalAlignment="Stretch" HorizontalContentAlignment="Center"
Command="{Binding WizardStartNewCommand}"/>
<Button Content="Ripristina da seed" FontSize="16"
HorizontalAlignment="Stretch" HorizontalContentAlignment="Center"
Command="{Binding WizardStartRestoreCommand}"/>
</StackPanel>
<!-- Apri wallet esistente -->
<Border IsVisible="{Binding WalletFileExists}"
BorderBrush="{DynamicResource SystemAccentColor}" BorderThickness="1"
CornerRadius="6" Padding="14">
<StackPanel Spacing="8">
<TextBlock Text="Apri il wallet esistente" FontWeight="Bold"/>
<TextBox PlaceholderText="Password del file (vuoto se non impostata)"
PasswordChar="●" Text="{Binding PasswordInput}"/>
<Button Content="Apri wallet" Command="{Binding OpenExistingCommand}"/>
<!-- Passo: password del wallet esistente -->
<StackPanel IsVisible="{Binding IsStepOpen}" Spacing="12">
<TextBlock Text="Apri il wallet" FontSize="18" FontWeight="Bold"/>
<TextBox PlaceholderText="Password del file (vuoto se non impostata)"
PasswordChar="●" Text="{Binding PasswordInput}"/>
<StackPanel Orientation="Horizontal" Spacing="10">
<Button Content="Indietro" Command="{Binding WizardBackCommand}"/>
<Button Content="Apri" Classes="accent" Command="{Binding OpenExistingCommand}"/>
</StackPanel>
</Border>
</StackPanel>
<!-- Crea / ripristina -->
<Border BorderBrush="Gray" BorderThickness="1" CornerRadius="6" Padding="14">
<StackPanel Spacing="8">
<TextBlock Text="Crea nuovo o ripristina da seed" FontWeight="Bold"/>
<TextBox PlaceholderText="Mnemonica BIP39 (12 o 24 parole)"
AcceptsReturn="False" Text="{Binding MnemonicInput}"/>
<Button Content="Genera nuova mnemonica" Command="{Binding GenerateMnemonicCommand}"/>
<TextBox PlaceholderText="Passphrase BIP39 opzionale (cambia il wallet! annotala a parte)"
Text="{Binding PassphraseInput}"/>
<TextBox PlaceholderText="Password di cifratura del file wallet (consigliata)"
PasswordChar="●" Text="{Binding PasswordInput}"/>
<Button Content="Crea / ripristina wallet" Command="{Binding CreateOrRestoreCommand}"/>
<!-- Passo: mostra il nuovo seed -->
<StackPanel IsVisible="{Binding IsStepShowSeed}" Spacing="12">
<TextBlock Text="Il tuo seed (12 parole)" FontSize="18" FontWeight="Bold"/>
<Border BorderBrush="{DynamicResource SystemAccentColor}" BorderThickness="1"
CornerRadius="6" Padding="14">
<SelectableTextBlock Text="{Binding MnemonicInput}"
FontFamily="monospace" FontSize="16" TextWrapping="Wrap"/>
</Border>
<TextBlock Foreground="Orange" TextWrapping="Wrap"
Text="Scrivi le parole su carta, nell'ordine. Chi le possiede controlla i fondi; se le perdi, i fondi sono irrecuperabili."/>
<StackPanel Orientation="Horizontal" Spacing="10">
<Button Content="Indietro" Command="{Binding WizardBackCommand}"/>
<Button Content="Le ho scritte — Avanti" Classes="accent"
Command="{Binding WizardNextFromShowSeedCommand}"/>
</StackPanel>
</Border>
</StackPanel>
<!-- Passo: conferma del seed -->
<StackPanel IsVisible="{Binding IsStepConfirmSeed}" Spacing="12">
<TextBlock Text="Conferma il seed" FontSize="18" FontWeight="Bold"/>
<TextBox PlaceholderText="Reinserisci le 12 parole separate da spazi"
AcceptsReturn="False" Text="{Binding ConfirmMnemonicInput}"/>
<StackPanel Orientation="Horizontal" Spacing="10">
<Button Content="Indietro" Command="{Binding WizardBackCommand}"/>
<Button Content="Avanti" Classes="accent"
Command="{Binding WizardNextFromConfirmSeedCommand}"/>
</StackPanel>
</StackPanel>
<!-- Passo: inserimento seed (ripristino) -->
<StackPanel IsVisible="{Binding IsStepWords}" Spacing="12">
<TextBlock Text="Ripristina da seed" FontSize="18" FontWeight="Bold"/>
<TextBox PlaceholderText="Mnemonica BIP39 (12 o 24 parole separate da spazi)"
AcceptsReturn="False" Text="{Binding MnemonicInput}"/>
<StackPanel Orientation="Horizontal" Spacing="10">
<Button Content="Indietro" Command="{Binding WizardBackCommand}"/>
<Button Content="Avanti" Classes="accent"
Command="{Binding WizardNextFromWordsCommand}"/>
</StackPanel>
</StackPanel>
<!-- Passo: passphrase opzionale -->
<StackPanel IsVisible="{Binding IsStepPassphrase}" Spacing="12">
<TextBlock Text="Passphrase opzionale" FontSize="18" FontWeight="Bold"/>
<TextBox PlaceholderText="Lascia vuoto per non usarla"
Text="{Binding PassphraseInput}"/>
<StackPanel Orientation="Horizontal" Spacing="10">
<Button Content="Indietro" Command="{Binding WizardBackCommand}"/>
<Button Content="Avanti" Classes="accent"
Command="{Binding WizardNextFromPassphraseCommand}"/>
</StackPanel>
</StackPanel>
<!-- Passo finale: password del file -->
<StackPanel IsVisible="{Binding IsStepPassword}" Spacing="12">
<TextBlock Text="Password del file wallet" FontSize="18" FontWeight="Bold"/>
<TextBox PlaceholderText="Consigliata (vuoto = file in chiaro su disco)"
PasswordChar="●" Text="{Binding PasswordInput}"/>
<StackPanel Orientation="Horizontal" Spacing="10">
<Button Content="Indietro" Command="{Binding WizardBackCommand}"/>
<Button Content="Crea il wallet" Classes="accent"
Command="{Binding CreateOrRestoreCommand}"/>
</StackPanel>
</StackPanel>
</StackPanel>
</ScrollViewer>