1686 lines
115 KiB
XML
1686 lines
115 KiB
XML
<UserControl xmlns="https://github.com/avaloniaui"
|
|
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
|
xmlns:vm="using:PalladiumWallet.App.ViewModels"
|
|
xmlns:net="using:PalladiumWallet.Core.Net"
|
|
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
|
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
|
mc:Ignorable="d" d:DesignWidth="900" d:DesignHeight="620"
|
|
x:Class="PalladiumWallet.App.Views.MainView"
|
|
x:DataType="vm:MainWindowViewModel">
|
|
|
|
<Design.DataContext>
|
|
<vm:MainWindowViewModel/>
|
|
</Design.DataContext>
|
|
|
|
<UserControl.Styles>
|
|
<!-- On desktop, overlay cards are centred with a max size;
|
|
on mobile the default (stretch, no margin) fills the whole screen. -->
|
|
<Style Selector="Border.desktop-overlay">
|
|
<Setter Property="MaxWidth" Value="540"/>
|
|
<Setter Property="MaxHeight" Value="540"/>
|
|
<Setter Property="Margin" Value="16"/>
|
|
<Setter Property="HorizontalAlignment" Value="Center"/>
|
|
<Setter Property="VerticalAlignment" Value="Center"/>
|
|
<Setter Property="CornerRadius" Value="8"/>
|
|
</Style>
|
|
</UserControl.Styles>
|
|
|
|
<Grid RowDefinitions="Auto,*,Auto" Background="{DynamicResource AppBackgroundBrush}">
|
|
|
|
<!-- ============ MENU (Electrum style) ============ -->
|
|
<Menu Grid.Row="0" IsVisible="{Binding IsDesktop}">
|
|
<MenuItem Header="{Binding Loc[menu.file]}">
|
|
<MenuItem Header="{Binding Loc[menu.file.new]}" Command="{Binding NewWalletCommand}"/>
|
|
<Separator/>
|
|
<MenuItem Header="{Binding Loc[menu.file.close]}" Command="{Binding CloseWalletCommand}"
|
|
IsEnabled="{Binding IsWalletOpen}"/>
|
|
<Separator/>
|
|
<MenuItem Header="{Binding Loc[menu.file.quit]}" Command="{Binding QuitAppCommand}"/>
|
|
</MenuItem>
|
|
<MenuItem Header="{Binding Loc[menu.wallet]}"
|
|
Command="{Binding OpenWalletInfoCommand}"
|
|
IsVisible="{Binding IsWalletOpen}"/>
|
|
<MenuItem Header="{Binding Loc[menu.settings]}"
|
|
Command="{Binding OpenSettingsCommand}"/>
|
|
<MenuItem Header="{Binding Loc[menu.help]}"
|
|
Command="{Binding OpenHelpCommand}"/>
|
|
</Menu>
|
|
|
|
<!-- Settings/Help buttons — mobile only (the menu is hidden on mobile) -->
|
|
<StackPanel Grid.Row="0" Orientation="Horizontal" Spacing="8"
|
|
HorizontalAlignment="Right" Margin="8,4"
|
|
IsVisible="{Binding IsMobile}">
|
|
<Button Content="{Binding Loc[menu.wallet]}"
|
|
Command="{Binding OpenWalletInfoCommand}"
|
|
IsVisible="{Binding IsWalletOpen}"/>
|
|
<Button Content="{Binding Loc[menu.settings]}" Command="{Binding OpenSettingsCommand}"/>
|
|
<Button Content="{Binding Loc[menu.help]}" Command="{Binding OpenHelpCommand}"/>
|
|
</StackPanel>
|
|
|
|
<!-- ============ SETUP WIZARD (§15): one step at a time ============ -->
|
|
<ScrollViewer Grid.Row="1" IsVisible="{Binding IsSetupVisible}">
|
|
<StackPanel MaxWidth="560" Margin="24,40" Spacing="18"
|
|
HorizontalAlignment="Center">
|
|
<TextBlock Text="Palladium Wallet" FontSize="28" FontWeight="Bold"
|
|
HorizontalAlignment="Center"/>
|
|
|
|
<!-- Step 0 (first launch): where to store data -->
|
|
<StackPanel IsVisible="{Binding IsStepDataLocation}" Spacing="12">
|
|
<TextBlock Text="{Binding Loc[wiz.data.title]}" FontSize="18" FontWeight="Bold"/>
|
|
<TextBlock Text="{Binding Loc[wiz.data.info]}" TextWrapping="Wrap" Foreground="{DynamicResource TextSecondaryBrush}"/>
|
|
<StackPanel Spacing="4">
|
|
<TextBlock Text="{Binding Loc[wiz.data.default]}" FontSize="11" Foreground="{DynamicResource TextSecondaryBrush}"/>
|
|
<SelectableTextBlock Text="{Binding DefaultDataPath}"
|
|
FontFamily="monospace" FontSize="13" TextWrapping="Wrap"/>
|
|
</StackPanel>
|
|
<Button Content="{Binding Loc[wiz.data.usedefault]}" FontSize="16" Classes="accent"
|
|
HorizontalAlignment="Stretch" HorizontalContentAlignment="Center"
|
|
Command="{Binding UseDefaultDataLocationCommand}"/>
|
|
<Button Content="{Binding Loc[wiz.data.choose]}" FontSize="16"
|
|
HorizontalAlignment="Stretch" HorizontalContentAlignment="Center"
|
|
Click="OnChooseDataFolderClick"/>
|
|
</StackPanel>
|
|
|
|
<!-- Step 1: initial choice -->
|
|
<StackPanel IsVisible="{Binding IsStepStart}" Spacing="12">
|
|
<Button Content="{Binding Loc[wiz.open.btn]}" FontSize="16"
|
|
HorizontalAlignment="Stretch" HorizontalContentAlignment="Center"
|
|
IsVisible="{Binding WalletFileExists}"
|
|
Command="{Binding WizardStartOpenCommand}"/>
|
|
<Button Content="{Binding Loc[wiz.new.btn]}" FontSize="16"
|
|
HorizontalAlignment="Stretch" HorizontalContentAlignment="Center"
|
|
Command="{Binding WizardStartNewCommand}"/>
|
|
<Button Content="{Binding Loc[wiz.restore.btn]}" FontSize="16"
|
|
HorizontalAlignment="Stretch" HorizontalContentAlignment="Center"
|
|
Command="{Binding WizardStartRestoreCommand}"/>
|
|
<Button Content="{Binding Loc[wiz.importxkey.btn]}" FontSize="16"
|
|
HorizontalAlignment="Stretch" HorizontalContentAlignment="Center"
|
|
Command="{Binding WizardStartImportXkeyCommand}"/>
|
|
<Button Content="{Binding Loc[wiz.importwif.btn]}" FontSize="16"
|
|
HorizontalAlignment="Stretch" HorizontalContentAlignment="Center"
|
|
Command="{Binding WizardStartImportWifCommand}"/>
|
|
</StackPanel>
|
|
|
|
<!-- Step: choose wallet (multiple files present) -->
|
|
<StackPanel IsVisible="{Binding IsStepChooseWallet}" Spacing="12">
|
|
<TextBlock Text="{Binding Loc[wiz.choose.title]}" FontSize="18" FontWeight="Bold"/>
|
|
<ItemsControl ItemsSource="{Binding WalletList}">
|
|
<ItemsControl.ItemTemplate>
|
|
<DataTemplate x:DataType="vm:WalletFileEntry">
|
|
<Button Content="{Binding Name}" FontFamily="monospace"
|
|
HorizontalAlignment="Stretch" HorizontalContentAlignment="Left"
|
|
Margin="0,0,0,6"
|
|
Command="{Binding $parent[ItemsControl].((vm:MainWindowViewModel)DataContext).ChooseWalletCommand}"
|
|
CommandParameter="{Binding}"/>
|
|
</DataTemplate>
|
|
</ItemsControl.ItemTemplate>
|
|
</ItemsControl>
|
|
<Button Content="{Binding Loc[wiz.back]}" Command="{Binding WizardBackCommand}"/>
|
|
</StackPanel>
|
|
|
|
<!-- Step: password for existing wallet -->
|
|
<StackPanel IsVisible="{Binding IsStepOpen}" Spacing="12">
|
|
<TextBlock Text="{Binding Loc[wiz.open.title]}" FontSize="18" FontWeight="Bold"/>
|
|
<TextBox PlaceholderText="{Binding Loc[wiz.open.placeholder]}"
|
|
PasswordChar="●" Text="{Binding PasswordInput}"/>
|
|
<StackPanel Orientation="Horizontal" Spacing="10">
|
|
<Button Content="{Binding Loc[wiz.back]}" Command="{Binding WizardBackCommand}"/>
|
|
<Button Content="{Binding Loc[wiz.open.ok]}" Classes="accent"
|
|
Command="{Binding OpenExistingCommand}"/>
|
|
</StackPanel>
|
|
</StackPanel>
|
|
|
|
<!-- Step: show the new seed -->
|
|
<StackPanel IsVisible="{Binding IsStepShowSeed}" Spacing="12">
|
|
<TextBlock Text="{Binding Loc[wiz.seed.title]}" 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="{DynamicResource WarningBrush}" TextWrapping="Wrap"
|
|
Text="{Binding Loc[wiz.seed.warning]}"/>
|
|
<StackPanel Orientation="Horizontal" Spacing="10">
|
|
<Button Content="{Binding Loc[wiz.back]}" Command="{Binding WizardBackCommand}"/>
|
|
<Button Content="{Binding Loc[wiz.seed.next]}" Classes="accent"
|
|
Command="{Binding WizardNextFromShowSeedCommand}"/>
|
|
</StackPanel>
|
|
</StackPanel>
|
|
|
|
<!-- Step: seed confirmation -->
|
|
<StackPanel IsVisible="{Binding IsStepConfirmSeed}" Spacing="12">
|
|
<TextBlock Text="{Binding Loc[wiz.confirm.title]}" FontSize="18" FontWeight="Bold"/>
|
|
<TextBox PlaceholderText="{Binding Loc[wiz.confirm.placeholder]}"
|
|
AcceptsReturn="False" Text="{Binding ConfirmMnemonicInput}"/>
|
|
<StackPanel Orientation="Horizontal" Spacing="10">
|
|
<Button Content="{Binding Loc[wiz.back]}" Command="{Binding WizardBackCommand}"/>
|
|
<Button Content="{Binding Loc[wiz.next]}" Classes="accent"
|
|
Command="{Binding WizardNextFromConfirmSeedCommand}"/>
|
|
</StackPanel>
|
|
</StackPanel>
|
|
|
|
<!-- Step: enter seed words (restore) -->
|
|
<StackPanel IsVisible="{Binding IsStepWords}" Spacing="12">
|
|
<TextBlock Text="{Binding Loc[wiz.words.title]}" FontSize="18" FontWeight="Bold"/>
|
|
<TextBox PlaceholderText="{Binding Loc[wiz.words.placeholder]}"
|
|
AcceptsReturn="False" Text="{Binding MnemonicInput}"/>
|
|
<StackPanel Orientation="Horizontal" Spacing="10">
|
|
<Button Content="{Binding Loc[wiz.back]}" Command="{Binding WizardBackCommand}"/>
|
|
<Button Content="{Binding Loc[wiz.next]}" Classes="accent"
|
|
Command="{Binding WizardNextFromWordsCommand}"/>
|
|
</StackPanel>
|
|
</StackPanel>
|
|
|
|
<!-- Step: optional passphrase -->
|
|
<StackPanel IsVisible="{Binding IsStepPassphrase}" Spacing="12">
|
|
<TextBlock Text="{Binding Loc[wiz.passphrase.title]}" FontSize="18" FontWeight="Bold"/>
|
|
<TextBox PlaceholderText="{Binding Loc[wiz.passphrase.placeholder]}"
|
|
Text="{Binding PassphraseInput}"/>
|
|
<StackPanel Orientation="Horizontal" Spacing="10">
|
|
<Button Content="{Binding Loc[wiz.back]}" Command="{Binding WizardBackCommand}"/>
|
|
<Button Content="{Binding Loc[wiz.next]}" Classes="accent"
|
|
Command="{Binding WizardNextFromPassphraseCommand}"/>
|
|
</StackPanel>
|
|
</StackPanel>
|
|
|
|
<!-- Step: import extended xpub/xprv (SLIP-132) -->
|
|
<StackPanel IsVisible="{Binding IsStepImportXkey}" Spacing="12">
|
|
<TextBlock Text="{Binding Loc[wiz.importxkey.title]}" FontSize="18" FontWeight="Bold"/>
|
|
<TextBlock Text="{Binding Loc[wiz.importxkey.hint]}" TextWrapping="Wrap" Foreground="{DynamicResource TextSecondaryBrush}"/>
|
|
<TextBox PlaceholderText="{Binding Loc[wiz.importxkey.placeholder]}"
|
|
Text="{Binding ImportXkeyInput}" AcceptsReturn="False"/>
|
|
<TextBlock Text="{Binding ImportXkeyDetectedKind}"
|
|
IsVisible="{Binding ImportXkeyDetectedKind, Converter={x:Static StringConverters.IsNotNullOrEmpty}}"
|
|
Foreground="{DynamicResource SuccessBrush}" FontSize="12"/>
|
|
<StackPanel Orientation="Horizontal" Spacing="10">
|
|
<Button Content="{Binding Loc[wiz.back]}" Command="{Binding WizardBackCommand}"/>
|
|
<Button Content="{Binding Loc[wiz.next]}" Classes="accent"
|
|
Command="{Binding WizardNextFromImportXkeyCommand}"/>
|
|
</StackPanel>
|
|
</StackPanel>
|
|
|
|
<!-- Step: import single WIF key -->
|
|
<StackPanel IsVisible="{Binding IsStepImportWif}" Spacing="12">
|
|
<TextBlock Text="{Binding Loc[wiz.importwif.title]}" FontSize="18" FontWeight="Bold"/>
|
|
<TextBlock Text="{Binding Loc[wiz.importwif.hint]}" TextWrapping="Wrap" Foreground="{DynamicResource TextSecondaryBrush}"/>
|
|
<TextBox PlaceholderText="{Binding Loc[wiz.importwif.placeholder]}"
|
|
Text="{Binding ImportWifInput}" AcceptsReturn="True" Height="80"/>
|
|
<StackPanel Orientation="Horizontal" Spacing="10">
|
|
<Button Content="{Binding Loc[wiz.back]}" Command="{Binding WizardBackCommand}"/>
|
|
<Button Content="{Binding Loc[wiz.next]}" Classes="accent"
|
|
Command="{Binding WizardNextFromImportWifCommand}"/>
|
|
</StackPanel>
|
|
</StackPanel>
|
|
|
|
<!-- Step: choose script/address type -->
|
|
<StackPanel IsVisible="{Binding IsStepScriptType}" Spacing="12">
|
|
<TextBlock Text="{Binding Loc[wiz.scripttype.title]}" FontSize="18" FontWeight="Bold"/>
|
|
<TextBlock Text="{Binding Loc[wiz.scripttype.hint]}" TextWrapping="Wrap" Foreground="{DynamicResource TextSecondaryBrush}"/>
|
|
|
|
<RadioButton GroupName="ScriptType"
|
|
IsChecked="{Binding IsLegacySelected, Mode=OneWay}"
|
|
Command="{Binding SelectLegacyCommand}">
|
|
<StackPanel Spacing="2">
|
|
<TextBlock Text="Legacy (P2PKH)" FontWeight="SemiBold"/>
|
|
<TextBlock Text="{Binding Loc[wiz.scripttype.legacy.desc]}" Foreground="{DynamicResource TextSecondaryBrush}" FontSize="12"/>
|
|
</StackPanel>
|
|
</RadioButton>
|
|
|
|
<RadioButton GroupName="ScriptType"
|
|
IsChecked="{Binding IsWrappedSegwitSelected, Mode=OneWay}"
|
|
Command="{Binding SelectWrappedSegwitCommand}">
|
|
<StackPanel Spacing="2">
|
|
<TextBlock Text="Wrapped SegWit (P2SH-P2WPKH)" FontWeight="SemiBold"/>
|
|
<TextBlock Text="{Binding Loc[wiz.scripttype.wrapped.desc]}" Foreground="{DynamicResource TextSecondaryBrush}" FontSize="12"/>
|
|
</StackPanel>
|
|
</RadioButton>
|
|
|
|
<RadioButton GroupName="ScriptType"
|
|
IsChecked="{Binding IsNativeSegwitSelected, Mode=OneWay}"
|
|
Command="{Binding SelectNativeSegwitCommand}">
|
|
<StackPanel Spacing="2">
|
|
<TextBlock Text="Native SegWit (P2WPKH)" FontWeight="SemiBold"/>
|
|
<TextBlock Text="{Binding Loc[wiz.scripttype.native.desc]}" Foreground="{DynamicResource TextSecondaryBrush}" FontSize="12"/>
|
|
</StackPanel>
|
|
</RadioButton>
|
|
|
|
<RadioButton GroupName="ScriptType"
|
|
IsChecked="{Binding IsTaprootSelected, Mode=OneWay}"
|
|
Command="{Binding SelectTaprootCommand}">
|
|
<StackPanel Spacing="2">
|
|
<TextBlock Text="Taproot (P2TR)" FontWeight="SemiBold"/>
|
|
<TextBlock Text="{Binding Loc[wiz.scripttype.taproot.desc]}" Foreground="{DynamicResource TextSecondaryBrush}" FontSize="12"/>
|
|
</StackPanel>
|
|
</RadioButton>
|
|
|
|
<StackPanel Orientation="Horizontal" Spacing="10">
|
|
<Button Content="{Binding Loc[wiz.back]}" Command="{Binding WizardBackCommand}"/>
|
|
<Button Content="{Binding Loc[wiz.next]}" Classes="accent"
|
|
Command="{Binding WizardNextFromScriptTypeCommand}"/>
|
|
</StackPanel>
|
|
</StackPanel>
|
|
|
|
<!-- Final step: wallet name + file password (encryption, Electrum style) -->
|
|
<StackPanel IsVisible="{Binding IsStepPassword}" Spacing="16">
|
|
<TextBlock Text="{Binding Loc[wiz.password.title]}" FontSize="18" FontWeight="Bold"/>
|
|
|
|
<!-- Name section: visually distinct from the password group -->
|
|
<Border BorderBrush="{DynamicResource SystemAccentColor}"
|
|
BorderThickness="0,0,0,0"
|
|
Background="{DynamicResource SurfaceAltBrush}"
|
|
CornerRadius="6" Padding="12,10">
|
|
<StackPanel Spacing="6">
|
|
<TextBlock Text="{Binding Loc[wiz.name.label]}"
|
|
FontWeight="SemiBold" FontSize="13"/>
|
|
<TextBox PlaceholderText="{Binding Loc[wiz.name.placeholder]}"
|
|
Text="{Binding WalletNameInput}"/>
|
|
</StackPanel>
|
|
</Border>
|
|
|
|
<!-- Visual separator -->
|
|
<Separator Margin="0,0"/>
|
|
|
|
<!-- Encryption section -->
|
|
<StackPanel Spacing="8">
|
|
<TextBox PlaceholderText="{Binding Loc[wiz.password.placeholder]}"
|
|
PasswordChar="●" Text="{Binding PasswordInput}"/>
|
|
<TextBox PlaceholderText="{Binding Loc[wiz.password.confirm]}"
|
|
PasswordChar="●" Text="{Binding ConfirmPasswordInput}"/>
|
|
<CheckBox Content="{Binding Loc[wiz.password.encrypt]}"
|
|
IsChecked="{Binding EncryptWallet}"/>
|
|
<TextBlock Text="{Binding Loc[wiz.password.encrypt.hint]}"
|
|
Foreground="{DynamicResource TextSecondaryBrush}" FontSize="12" TextWrapping="Wrap"
|
|
IsVisible="{Binding !EncryptWallet}"/>
|
|
</StackPanel>
|
|
|
|
<StackPanel Orientation="Horizontal" Spacing="10">
|
|
<Button Content="{Binding Loc[wiz.back]}" Command="{Binding WizardBackCommand}"/>
|
|
<Button Content="{Binding Loc[wiz.password.create]}" Classes="accent"
|
|
Command="{Binding CreateOrRestoreCommand}"/>
|
|
</StackPanel>
|
|
</StackPanel>
|
|
</StackPanel>
|
|
</ScrollViewer>
|
|
|
|
<!-- ============ WALLET PANEL ============ -->
|
|
<Grid Grid.Row="1" RowDefinitions="Auto,*" IsVisible="{Binding IsWalletOpen}" Margin="16">
|
|
|
|
<!-- Header: balance card. Connect/sync is automatic; close wallet is in File.
|
|
Connection status is shown in the bottom bar. -->
|
|
<Border Grid.Row="0" Classes="balance-hero" Margin="0,0,0,16">
|
|
<StackPanel Spacing="4">
|
|
<TextBlock Text="{Binding Loc[addr.balance]}" Classes="label on-hero"/>
|
|
<TextBlock Text="{Binding BalanceText}" Classes="amount"/>
|
|
<TextBlock Text="{Binding UnconfirmedText}" Foreground="#FCD34D"
|
|
TextWrapping="Wrap"
|
|
IsVisible="{Binding UnconfirmedText, Converter={x:Static StringConverters.IsNotNullOrEmpty}}"/>
|
|
<TextBlock Text="{Binding ImmatureText}" Foreground="#FCD34D"
|
|
TextWrapping="Wrap"
|
|
IsVisible="{Binding ImmatureText, Converter={x:Static StringConverters.IsNotNullOrEmpty}}"/>
|
|
<TextBlock Text="{Binding VerifyingText}" Foreground="#FCD34D"
|
|
TextWrapping="Wrap"
|
|
IsVisible="{Binding VerifyingText, Converter={x:Static StringConverters.IsNotNullOrEmpty}}"/>
|
|
<TextBlock Text="{Binding NetworkInfo}" Classes="on-hero" FontSize="12"
|
|
Margin="0,2,0,0"/>
|
|
</StackPanel>
|
|
</Border>
|
|
|
|
<!-- Tabs: History / Send / Receive / Addresses / Contacts -->
|
|
<TabControl Grid.Row="1"
|
|
SelectedIndex="{Binding SelectedTabIndex}"
|
|
TabStripPlacement="Top">
|
|
|
|
<TabControl.Styles>
|
|
<Style Selector="TabStrip">
|
|
<Setter Property="HorizontalAlignment" Value="Stretch"/>
|
|
<Setter Property="Background" Value="{DynamicResource SurfaceBrush}"/>
|
|
<Setter Property="ItemsPanel">
|
|
<ItemsPanelTemplate>
|
|
<UniformGrid Rows="1" Columns="5"/>
|
|
</ItemsPanelTemplate>
|
|
</Setter>
|
|
</Style>
|
|
<Style Selector="TabItem">
|
|
<Setter Property="HorizontalAlignment" Value="Stretch"/>
|
|
<Setter Property="HorizontalContentAlignment" Value="Center"/>
|
|
<Setter Property="VerticalContentAlignment" Value="Center"/>
|
|
<Setter Property="Padding" Value="8,12"/>
|
|
</Style>
|
|
</TabControl.Styles>
|
|
|
|
<!-- 1. History -->
|
|
<TabItem>
|
|
<TabItem.Header>
|
|
<StackPanel Spacing="{Binding $parent[TabControl].((vm:MainWindowViewModel)DataContext).TabSpacing}"
|
|
HorizontalAlignment="Center">
|
|
<Viewbox Width="{Binding $parent[TabControl].((vm:MainWindowViewModel)DataContext).TabIconSize}"
|
|
Height="{Binding $parent[TabControl].((vm:MainWindowViewModel)DataContext).TabIconSize}"
|
|
HorizontalAlignment="Center">
|
|
<Canvas Width="24" Height="24">
|
|
<Path Fill="{Binding $parent[TabItem].Foreground}"
|
|
Data="M7,5H21V7H7V5M7,13V11H21V13H7M4,4.5A1.5,1.5 0 0,1 5.5,6A1.5,1.5 0 0,1 4,7.5A1.5,1.5 0 0,1 2.5,6A1.5,1.5 0 0,1 4,4.5M4,10.5A1.5,1.5 0 0,1 5.5,12A1.5,1.5 0 0,1 4,13.5A1.5,1.5 0 0,1 2.5,12A1.5,1.5 0 0,1 4,10.5M7,19V17H21V19H7M4,16.5A1.5,1.5 0 0,1 5.5,18A1.5,1.5 0 0,1 4,19.5A1.5,1.5 0 0,1 2.5,18A1.5,1.5 0 0,1 4,16.5Z"/>
|
|
</Canvas>
|
|
</Viewbox>
|
|
<TextBlock Text="{Binding Loc[tab.history]}"
|
|
FontSize="{Binding $parent[TabControl].((vm:MainWindowViewModel)DataContext).TabFontSize}"
|
|
HorizontalAlignment="Center"/>
|
|
</StackPanel>
|
|
</TabItem.Header>
|
|
<Grid RowDefinitions="Auto,*" Margin="4">
|
|
<TextBlock Grid.Row="0" Text="{Binding Loc[history.hint]}"
|
|
IsVisible="{Binding IsDesktop}"
|
|
Foreground="{DynamicResource TextSecondaryBrush}" FontSize="11" Margin="6,2"/>
|
|
<ListBox Grid.Row="1" ItemsSource="{Binding History}"
|
|
DoubleTapped="OnHistoryRowDoubleTapped">
|
|
<ListBox.ItemTemplate>
|
|
<DataTemplate x:DataType="vm:HistoryRow">
|
|
<Panel Cursor="Hand">
|
|
<!-- Desktop: 3 fixed columns -->
|
|
<Grid ColumnDefinitions="90,160,*,Auto"
|
|
IsVisible="{Binding $parent[UserControl].((vm:MainWindowViewModel)DataContext).IsDesktop}">
|
|
<TextBlock Grid.Column="0" Text="{Binding Conferma}" Foreground="{DynamicResource TextSecondaryBrush}"/>
|
|
<TextBlock Grid.Column="1" Text="{Binding Importo}" FontFamily="monospace"/>
|
|
<TextBlock Grid.Column="2" Text="{Binding Txid}"
|
|
FontFamily="monospace" FontSize="12"
|
|
TextTrimming="CharacterEllipsis"/>
|
|
<TextBlock Grid.Column="3" Text="{Binding $parent[UserControl].((vm:MainWindowViewModel)DataContext).Loc[history.unverified]}"
|
|
Foreground="#FCD34D" FontSize="11" Margin="6,0,0,0"
|
|
IsVisible="{Binding !Verified}"/>
|
|
</Grid>
|
|
<!-- Mobile: vertical card -->
|
|
<StackPanel Spacing="2"
|
|
IsVisible="{Binding $parent[UserControl].((vm:MainWindowViewModel)DataContext).IsMobile}">
|
|
<TextBlock Text="{Binding Importo}"
|
|
FontFamily="monospace" FontWeight="SemiBold"/>
|
|
<TextBlock Text="{Binding Conferma}" Foreground="{DynamicResource TextSecondaryBrush}" FontSize="11"/>
|
|
<TextBlock Text="{Binding Txid}" FontFamily="monospace" FontSize="11"
|
|
TextTrimming="CharacterEllipsis"/>
|
|
<TextBlock Text="{Binding $parent[UserControl].((vm:MainWindowViewModel)DataContext).Loc[history.unverified]}"
|
|
Foreground="#FCD34D" FontSize="11"
|
|
IsVisible="{Binding !Verified}"/>
|
|
</StackPanel>
|
|
</Panel>
|
|
</DataTemplate>
|
|
</ListBox.ItemTemplate>
|
|
</ListBox>
|
|
</Grid>
|
|
</TabItem>
|
|
|
|
<!-- 2. Send -->
|
|
<TabItem>
|
|
<TabItem.Header>
|
|
<StackPanel Spacing="{Binding $parent[TabControl].((vm:MainWindowViewModel)DataContext).TabSpacing}"
|
|
HorizontalAlignment="Center">
|
|
<Viewbox Width="{Binding $parent[TabControl].((vm:MainWindowViewModel)DataContext).TabIconSize}"
|
|
Height="{Binding $parent[TabControl].((vm:MainWindowViewModel)DataContext).TabIconSize}"
|
|
HorizontalAlignment="Center">
|
|
<Canvas Width="24" Height="24">
|
|
<Path Fill="{Binding $parent[TabItem].Foreground}"
|
|
Data="M2,21L23,12L2,3V10L17,12L2,14V21Z"/>
|
|
</Canvas>
|
|
</Viewbox>
|
|
<TextBlock Text="{Binding Loc[tab.send]}"
|
|
FontSize="{Binding $parent[TabControl].((vm:MainWindowViewModel)DataContext).TabFontSize}"
|
|
HorizontalAlignment="Center"/>
|
|
</StackPanel>
|
|
</TabItem.Header>
|
|
<ScrollViewer>
|
|
<Panel Margin="16,14">
|
|
|
|
<!-- ── DESKTOP: Recipient | Amount side-by-side ── -->
|
|
<Grid IsVisible="{Binding IsDesktop}"
|
|
RowDefinitions="Auto,Auto,Auto" RowSpacing="14">
|
|
|
|
<Grid Grid.Row="0" ColumnDefinitions="*,*" ColumnSpacing="14">
|
|
<!-- Recipient card -->
|
|
<Border Grid.Column="0" Classes="card" Padding="22,18">
|
|
<StackPanel Spacing="14">
|
|
<TextBlock Text="{Binding Loc[send.sect.recipient]}" Classes="section"/>
|
|
<Grid ColumnDefinitions="Auto,*">
|
|
<TextBlock Grid.Column="0" Text="{Binding Loc[send.from.contact]}"
|
|
VerticalAlignment="Center" Margin="0,0,10,0"
|
|
Foreground="{DynamicResource TextSecondaryBrush}" FontSize="13"/>
|
|
<ComboBox Grid.Column="1" HorizontalAlignment="Stretch"
|
|
ItemsSource="{Binding Contacts}"
|
|
SelectedItem="{Binding SendToContact}"
|
|
PlaceholderText="{Binding Loc[send.contact.hint]}">
|
|
<ComboBox.ItemTemplate>
|
|
<DataTemplate x:DataType="vm:ContactEntry">
|
|
<TextBlock Text="{Binding Name}"/>
|
|
</DataTemplate>
|
|
</ComboBox.ItemTemplate>
|
|
</ComboBox>
|
|
</Grid>
|
|
<StackPanel Spacing="4">
|
|
<TextBlock Text="{Binding Loc[send.to]}" Classes="label"/>
|
|
<TextBox PlaceholderText="{Binding Loc[send.to]}"
|
|
Text="{Binding SendTo}"
|
|
FontFamily="monospace" FontSize="13"/>
|
|
</StackPanel>
|
|
</StackPanel>
|
|
</Border>
|
|
|
|
<!-- Amount & fee card -->
|
|
<Border Grid.Column="1" Classes="card" Padding="22,18">
|
|
<StackPanel Spacing="14">
|
|
<TextBlock Text="{Binding Loc[send.sect.amount]}" Classes="section"/>
|
|
<StackPanel Spacing="4">
|
|
<TextBlock Text="{Binding Loc[send.amount]}" Classes="label"/>
|
|
<Grid ColumnDefinitions="*,Auto,Auto">
|
|
<TextBox Grid.Column="0"
|
|
PlaceholderText="0.00000000"
|
|
Text="{Binding SendAmount}"
|
|
IsEnabled="{Binding !SendAll}"
|
|
FontFamily="monospace"/>
|
|
<TextBlock Grid.Column="1" Text="{Binding UnitLabel}"
|
|
VerticalAlignment="Center" Margin="10,0,0,0"
|
|
Foreground="{DynamicResource TextSecondaryBrush}"
|
|
FontWeight="Medium"/>
|
|
<CheckBox Grid.Column="2" Content="{Binding Loc[send.all]}"
|
|
IsChecked="{Binding SendAll}"
|
|
Margin="16,0,0,0" VerticalAlignment="Center"/>
|
|
</Grid>
|
|
</StackPanel>
|
|
<Grid ColumnDefinitions="Auto,*">
|
|
<TextBlock Grid.Column="0" Text="{Binding Loc[send.feerate]}"
|
|
VerticalAlignment="Center" Classes="label" Margin="0,0,12,0"/>
|
|
<TextBox Grid.Column="1" Text="{Binding SendFeeRate}"
|
|
MaxWidth="120" HorizontalAlignment="Left"
|
|
FontFamily="monospace"/>
|
|
</Grid>
|
|
</StackPanel>
|
|
</Border>
|
|
</Grid>
|
|
|
|
<!-- Summary card — full width, visible after Prepare -->
|
|
<Border Grid.Row="1" Classes="card" Padding="22,16"
|
|
IsVisible="{Binding SendPreview, Converter={x:Static StringConverters.IsNotNullOrEmpty}}">
|
|
<StackPanel Spacing="8">
|
|
<TextBlock Text="{Binding Loc[send.summary]}" Classes="section"/>
|
|
<SelectableTextBlock Text="{Binding SendPreview}"
|
|
TextWrapping="Wrap" FontSize="13" Classes="mono"
|
|
Foreground="{DynamicResource TextSecondaryBrush}"/>
|
|
</StackPanel>
|
|
</Border>
|
|
|
|
<!-- Action buttons -->
|
|
<Grid Grid.Row="2" ColumnDefinitions="*,*" ColumnSpacing="14">
|
|
<Button Grid.Column="0" Content="{Binding Loc[send.prepare]}"
|
|
Command="{Binding PrepareSendCommand}"
|
|
HorizontalAlignment="Stretch" HorizontalContentAlignment="Center"/>
|
|
<Button Grid.Column="1" Content="{Binding Loc[send.confirm]}" Classes="accent"
|
|
Command="{Binding ConfirmSendCommand}"
|
|
IsEnabled="{Binding HasPendingSend}"
|
|
HorizontalAlignment="Stretch" HorizontalContentAlignment="Center"/>
|
|
</Grid>
|
|
</Grid>
|
|
|
|
<!-- ── MOBILE: vertical stack ── -->
|
|
<StackPanel IsVisible="{Binding IsMobile}" Spacing="12">
|
|
|
|
<!-- Recipient card with labelled inputs -->
|
|
<Border Classes="card" Padding="20,18">
|
|
<StackPanel Spacing="14">
|
|
<TextBlock Text="{Binding Loc[send.sect.recipient]}" Classes="section"/>
|
|
<!-- Contact picker -->
|
|
<StackPanel Spacing="4">
|
|
<TextBlock Text="{Binding Loc[send.from.contact]}" Classes="label"/>
|
|
<ComboBox HorizontalAlignment="Stretch"
|
|
ItemsSource="{Binding Contacts}"
|
|
SelectedItem="{Binding SendToContact}"
|
|
PlaceholderText="{Binding Loc[send.contact.hint]}"
|
|
MinHeight="48">
|
|
<ComboBox.ItemTemplate>
|
|
<DataTemplate x:DataType="vm:ContactEntry">
|
|
<TextBlock Text="{Binding Name}" FontSize="15"/>
|
|
</DataTemplate>
|
|
</ComboBox.ItemTemplate>
|
|
</ComboBox>
|
|
</StackPanel>
|
|
<!-- Address + QR scan button -->
|
|
<StackPanel Spacing="4">
|
|
<TextBlock Text="{Binding Loc[send.to]}" Classes="label"/>
|
|
<Grid ColumnDefinitions="*,Auto">
|
|
<TextBox Grid.Column="0"
|
|
PlaceholderText="{Binding Loc[send.to]}"
|
|
Text="{Binding SendTo}"
|
|
FontFamily="monospace" FontSize="15"
|
|
MinHeight="48"/>
|
|
<Button Grid.Column="1" Margin="8,0,0,0"
|
|
Width="52" Height="48"
|
|
Command="{Binding ScanQrCommand}"
|
|
ToolTip.Tip="{Binding Loc[send.scan]}">
|
|
<Viewbox Width="22" Height="22">
|
|
<Canvas Width="24" Height="24">
|
|
<Path Fill="{DynamicResource SystemBaseHighColor}"
|
|
Data="M20,5H16.83L15,3H9L7.17,5H4A2,2 0 0,0 2,7V19A2,2 0 0,0 4,21H20A2,2 0 0,0 22,19V7A2,2 0 0,0 20,5M20,19H4V7H8.05L9.88,5H14.12L15.95,7H20V19M12,8A5,5 0 0,0 7,13A5,5 0 0,0 12,18A5,5 0 0,0 17,13A5,5 0 0,0 12,8M12,16A3,3 0 0,1 9,13A3,3 0 0,1 12,10A3,3 0 0,1 15,13A3,3 0 0,1 12,16Z"/>
|
|
</Canvas>
|
|
</Viewbox>
|
|
</Button>
|
|
</Grid>
|
|
</StackPanel>
|
|
</StackPanel>
|
|
</Border>
|
|
|
|
<!-- Amount & fee card with labelled inputs -->
|
|
<Border Classes="card" Padding="20,18">
|
|
<StackPanel Spacing="14">
|
|
<TextBlock Text="{Binding Loc[send.sect.amount]}" Classes="section"/>
|
|
<!-- Amount field -->
|
|
<StackPanel Spacing="4">
|
|
<TextBlock Text="{Binding Loc[send.amount]}" Classes="label"/>
|
|
<Grid ColumnDefinitions="*,Auto">
|
|
<TextBox Grid.Column="0"
|
|
PlaceholderText="0.00000000"
|
|
Text="{Binding SendAmount}"
|
|
IsEnabled="{Binding !SendAll}"
|
|
FontFamily="monospace" FontSize="16"
|
|
MinHeight="48"/>
|
|
<TextBlock Grid.Column="1" Text="{Binding UnitLabel}"
|
|
VerticalAlignment="Center" Margin="12,0,0,0"
|
|
FontWeight="Medium"
|
|
Foreground="{DynamicResource TextSecondaryBrush}"/>
|
|
</Grid>
|
|
</StackPanel>
|
|
<!-- Send-all toggle -->
|
|
<CheckBox Content="{Binding Loc[send.all]}"
|
|
IsChecked="{Binding SendAll}"
|
|
MinHeight="44" FontSize="14"/>
|
|
<!-- Fee rate field -->
|
|
<StackPanel Spacing="4">
|
|
<TextBlock Text="{Binding Loc[send.feerate]}" Classes="label"/>
|
|
<TextBox Text="{Binding SendFeeRate}"
|
|
FontFamily="monospace" FontSize="15"
|
|
MinHeight="48" HorizontalAlignment="Stretch"/>
|
|
</StackPanel>
|
|
</StackPanel>
|
|
</Border>
|
|
|
|
<!-- Summary card -->
|
|
<Border Classes="card" Padding="20,16"
|
|
IsVisible="{Binding SendPreview, Converter={x:Static StringConverters.IsNotNullOrEmpty}}">
|
|
<StackPanel Spacing="8">
|
|
<TextBlock Text="{Binding Loc[send.summary]}" Classes="section"/>
|
|
<SelectableTextBlock Text="{Binding SendPreview}"
|
|
TextWrapping="Wrap" FontSize="13" Classes="mono"
|
|
Foreground="{DynamicResource TextSecondaryBrush}"/>
|
|
</StackPanel>
|
|
</Border>
|
|
|
|
<!-- Action buttons: primary (Confirm) prominent, secondary below -->
|
|
<Button Content="{Binding Loc[send.confirm]}" Classes="accent"
|
|
Command="{Binding ConfirmSendCommand}"
|
|
IsEnabled="{Binding HasPendingSend}"
|
|
MinHeight="52"
|
|
HorizontalAlignment="Stretch" HorizontalContentAlignment="Center"
|
|
FontSize="15"/>
|
|
<Button Content="{Binding Loc[send.prepare]}"
|
|
Command="{Binding PrepareSendCommand}"
|
|
MinHeight="48"
|
|
HorizontalAlignment="Stretch" HorizontalContentAlignment="Center"/>
|
|
|
|
</StackPanel>
|
|
|
|
</Panel>
|
|
</ScrollViewer>
|
|
</TabItem>
|
|
|
|
<!-- 3. Receive -->
|
|
<TabItem>
|
|
<TabItem.Header>
|
|
<StackPanel Spacing="{Binding $parent[TabControl].((vm:MainWindowViewModel)DataContext).TabSpacing}"
|
|
HorizontalAlignment="Center">
|
|
<Viewbox Width="{Binding $parent[TabControl].((vm:MainWindowViewModel)DataContext).TabIconSize}"
|
|
Height="{Binding $parent[TabControl].((vm:MainWindowViewModel)DataContext).TabIconSize}"
|
|
HorizontalAlignment="Center">
|
|
<Canvas Width="24" Height="24">
|
|
<Path Fill="{Binding $parent[TabItem].Foreground}"
|
|
Data="M2,12H4V17H20V12H22V17A2,2 0 0,1 20,19H4A2,2 0 0,1 2,17V12M12,15L17,10L15.59,8.58L13,11.17V2H11V11.17L8.41,8.59L7,10L12,15Z"/>
|
|
</Canvas>
|
|
</Viewbox>
|
|
<TextBlock Text="{Binding Loc[tab.receive]}"
|
|
FontSize="{Binding $parent[TabControl].((vm:MainWindowViewModel)DataContext).TabFontSize}"
|
|
HorizontalAlignment="Center"/>
|
|
</StackPanel>
|
|
</TabItem.Header>
|
|
<ScrollViewer>
|
|
<Panel Margin="16,14">
|
|
|
|
<!-- ── DESKTOP: QR left | address right ── -->
|
|
<Grid IsVisible="{Binding IsDesktop}"
|
|
ColumnDefinitions="Auto,*" ColumnSpacing="14">
|
|
|
|
<!-- QR hero card -->
|
|
<Border Grid.Column="0" Classes="card" Padding="28,24"
|
|
IsVisible="{Binding ReceiveQr, Converter={x:Static ObjectConverters.IsNotNull}}">
|
|
<StackPanel Spacing="18" HorizontalAlignment="Center">
|
|
<TextBlock Text="{Binding Loc[receive.next]}" Classes="label"
|
|
HorizontalAlignment="Center"/>
|
|
<Border Background="White" Padding="14" CornerRadius="10"
|
|
HorizontalAlignment="Center">
|
|
<Image Source="{Binding ReceiveQr}" Width="230" Height="230"
|
|
RenderOptions.BitmapInterpolationMode="None"/>
|
|
</Border>
|
|
</StackPanel>
|
|
</Border>
|
|
|
|
<!-- Address + hint column -->
|
|
<StackPanel Grid.Column="1" Spacing="14" VerticalAlignment="Center">
|
|
<Border Classes="card" Padding="24,22">
|
|
<StackPanel Spacing="16">
|
|
<TextBlock Text="{Binding Loc[receive.your.address]}" Classes="section"/>
|
|
<Border Background="{DynamicResource SurfaceAltBrush}"
|
|
CornerRadius="8" Padding="16,14">
|
|
<SelectableTextBlock Text="{Binding ReceiveAddress}"
|
|
FontFamily="monospace" FontSize="14"
|
|
TextWrapping="Wrap" LineHeight="22"/>
|
|
</Border>
|
|
<Button Content="{Binding Loc[receive.copy]}" Classes="accent"
|
|
Click="OnCopyReceiveAddressClick"
|
|
HorizontalAlignment="Stretch"
|
|
HorizontalContentAlignment="Center"/>
|
|
</StackPanel>
|
|
</Border>
|
|
<TextBlock Text="{Binding Loc[receive.hint]}"
|
|
Foreground="{DynamicResource TextSecondaryBrush}" FontSize="12"
|
|
TextWrapping="Wrap" Margin="4,0"/>
|
|
</StackPanel>
|
|
</Grid>
|
|
|
|
<!-- ── MOBILE: vertical stack ── -->
|
|
<StackPanel IsVisible="{Binding IsMobile}" Spacing="12">
|
|
|
|
<!-- QR card: full-width, centered with generous padding -->
|
|
<Border Classes="card" Padding="24,22"
|
|
IsVisible="{Binding ReceiveQr, Converter={x:Static ObjectConverters.IsNotNull}}">
|
|
<StackPanel Spacing="16" HorizontalAlignment="Center">
|
|
<TextBlock Text="{Binding Loc[receive.next]}" Classes="label"
|
|
HorizontalAlignment="Center" FontSize="13"/>
|
|
<Border Background="White" Padding="16" CornerRadius="12"
|
|
HorizontalAlignment="Center">
|
|
<Image Source="{Binding ReceiveQr}" Width="220" Height="220"
|
|
RenderOptions.BitmapInterpolationMode="None"/>
|
|
</Border>
|
|
</StackPanel>
|
|
</Border>
|
|
|
|
<!-- Address card: label + monospace box + big Copy button -->
|
|
<Border Classes="card" Padding="20,20">
|
|
<StackPanel Spacing="14">
|
|
<TextBlock Text="{Binding Loc[receive.your.address]}" Classes="section"/>
|
|
<Border Background="{DynamicResource SurfaceAltBrush}"
|
|
CornerRadius="8" Padding="16,12">
|
|
<SelectableTextBlock Text="{Binding ReceiveAddress}"
|
|
FontFamily="monospace" FontSize="14"
|
|
TextWrapping="Wrap"
|
|
TextAlignment="Center"
|
|
HorizontalAlignment="Center"
|
|
LineHeight="22"/>
|
|
</Border>
|
|
<Button Content="{Binding Loc[receive.copy]}" Classes="accent"
|
|
Click="OnCopyReceiveAddressClick"
|
|
MinHeight="52"
|
|
HorizontalAlignment="Stretch"
|
|
HorizontalContentAlignment="Center"
|
|
FontSize="15"/>
|
|
</StackPanel>
|
|
</Border>
|
|
|
|
<!-- Hint -->
|
|
<TextBlock Text="{Binding Loc[receive.hint]}"
|
|
Foreground="{DynamicResource TextSecondaryBrush}" FontSize="12"
|
|
TextWrapping="Wrap" TextAlignment="Center" Margin="4,0"/>
|
|
|
|
</StackPanel>
|
|
|
|
</Panel>
|
|
</ScrollViewer>
|
|
</TabItem>
|
|
|
|
<!-- 4. Addresses -->
|
|
<TabItem>
|
|
<TabItem.Header>
|
|
<StackPanel Spacing="{Binding $parent[TabControl].((vm:MainWindowViewModel)DataContext).TabSpacing}"
|
|
HorizontalAlignment="Center">
|
|
<Viewbox Width="{Binding $parent[TabControl].((vm:MainWindowViewModel)DataContext).TabIconSize}"
|
|
Height="{Binding $parent[TabControl].((vm:MainWindowViewModel)DataContext).TabIconSize}"
|
|
HorizontalAlignment="Center">
|
|
<Canvas Width="24" Height="24">
|
|
<Path Fill="{Binding $parent[TabItem].Foreground}"
|
|
Data="M21,18V19A2,2 0 0,1 19,21H5C3.89,21 3,20.1 3,19V5A2,2 0 0,1 5,3H19A2,2 0 0,1 21,5V6H12C10.89,6 10,6.9 10,8V16A2,2 0 0,0 12,18H21M12,16H22V8H12V16M16,13.5A1.5,1.5 0 0,1 14.5,12A1.5,1.5 0 0,1 16,10.5A1.5,1.5 0 0,1 17.5,12A1.5,1.5 0 0,1 16,13.5Z"/>
|
|
</Canvas>
|
|
</Viewbox>
|
|
<TextBlock Text="{Binding Loc[tab.addresses]}"
|
|
FontSize="{Binding $parent[TabControl].((vm:MainWindowViewModel)DataContext).TabFontSize}"
|
|
HorizontalAlignment="Center"/>
|
|
</StackPanel>
|
|
</TabItem.Header>
|
|
<Grid RowDefinitions="Auto,*" Margin="4">
|
|
<!-- Column header — desktop only -->
|
|
<Grid Grid.Row="0" ColumnDefinitions="90,60,*,140,60" Margin="12,4"
|
|
IsVisible="{Binding IsDesktop}">
|
|
<TextBlock Grid.Column="0" Text="{Binding Loc[addr.type]}" FontWeight="Bold"/>
|
|
<TextBlock Grid.Column="1" Text="{Binding Loc[addr.index]}" FontWeight="Bold"/>
|
|
<TextBlock Grid.Column="2" Text="{Binding Loc[addr.address]}" FontWeight="Bold"/>
|
|
<TextBlock Grid.Column="3" Text="{Binding Loc[addr.balance]}" FontWeight="Bold"/>
|
|
<TextBlock Grid.Column="4" Text="Tx" FontWeight="Bold"/>
|
|
</Grid>
|
|
<ListBox Grid.Row="1" ItemsSource="{Binding Addresses}"
|
|
SelectedItem="{Binding SelectedAddressRow}"
|
|
x:Name="AddressesListBox"
|
|
Tapped="OnAddressListTapped"
|
|
PointerPressed="OnAddressListPointerPressed">
|
|
<ListBox.ItemTemplate>
|
|
<DataTemplate x:DataType="vm:AddressRow">
|
|
<Panel>
|
|
<!-- Desktop: 5 fixed columns -->
|
|
<Grid ColumnDefinitions="90,60,*,140,60"
|
|
IsVisible="{Binding $parent[UserControl].((vm:MainWindowViewModel)DataContext).IsDesktop}">
|
|
<TextBlock Grid.Column="0" Text="{Binding Tipo}" Foreground="{DynamicResource TextSecondaryBrush}"/>
|
|
<TextBlock Grid.Column="1" Text="{Binding Indice}" Foreground="{DynamicResource TextSecondaryBrush}"/>
|
|
<TextBlock Grid.Column="2" Text="{Binding Indirizzo}"
|
|
FontFamily="monospace" FontSize="13"/>
|
|
<TextBlock Grid.Column="3" Text="{Binding Saldo}" FontFamily="monospace"/>
|
|
<TextBlock Grid.Column="4" Text="{Binding NumTx}" Foreground="{DynamicResource TextSecondaryBrush}"/>
|
|
</Grid>
|
|
<!-- Mobile: vertical card -->
|
|
<StackPanel Spacing="1" Margin="0,3"
|
|
IsVisible="{Binding $parent[UserControl].((vm:MainWindowViewModel)DataContext).IsMobile}">
|
|
<TextBlock Text="{Binding Indirizzo}"
|
|
FontFamily="monospace" FontSize="12"
|
|
TextTrimming="CharacterEllipsis"/>
|
|
<StackPanel Orientation="Horizontal" Spacing="8">
|
|
<TextBlock Text="{Binding Tipo}" Foreground="{DynamicResource TextSecondaryBrush}" FontSize="11"/>
|
|
<TextBlock Text="{Binding Indice}" Foreground="{DynamicResource TextSecondaryBrush}" FontSize="11"/>
|
|
<TextBlock Text="{Binding Saldo}" FontFamily="monospace" FontSize="11"/>
|
|
<TextBlock Text="{Binding NumTx}" Foreground="{DynamicResource TextSecondaryBrush}" FontSize="11"/>
|
|
</StackPanel>
|
|
</StackPanel>
|
|
</Panel>
|
|
</DataTemplate>
|
|
</ListBox.ItemTemplate>
|
|
</ListBox>
|
|
</Grid>
|
|
</TabItem>
|
|
|
|
<!-- 5. Contacts -->
|
|
<TabItem>
|
|
<TabItem.Header>
|
|
<StackPanel Spacing="{Binding $parent[TabControl].((vm:MainWindowViewModel)DataContext).TabSpacing}"
|
|
HorizontalAlignment="Center">
|
|
<Viewbox Width="{Binding $parent[TabControl].((vm:MainWindowViewModel)DataContext).TabIconSize}"
|
|
Height="{Binding $parent[TabControl].((vm:MainWindowViewModel)DataContext).TabIconSize}"
|
|
HorizontalAlignment="Center">
|
|
<Canvas Width="24" Height="24">
|
|
<Path Fill="{Binding $parent[TabItem].Foreground}"
|
|
Data="M16,13C15.71,13 15.38,13 15.03,13.05C16.19,13.89 17,15 17,16.5V19H23V16.5C23,14.17 18.33,13 16,13M8,13C5.67,13 1,14.17 1,16.5V19H15V16.5C15,14.17 10.33,13 8,13M8,11A3,3 0 0,0 11,8A3,3 0 0,0 8,5A3,3 0 0,0 5,8A3,3 0 0,0 8,11M16,11A3,3 0 0,0 19,8A3,3 0 0,0 16,5C15.71,5 15.42,5.03 15.14,5.09C15.68,5.95 16,6.94 16,8C16,9.06 15.68,10.05 15.14,10.91C15.42,10.97 15.71,11 16,11Z"/>
|
|
</Canvas>
|
|
</Viewbox>
|
|
<TextBlock Text="{Binding Loc[tab.contacts]}"
|
|
FontSize="{Binding $parent[TabControl].((vm:MainWindowViewModel)DataContext).TabFontSize}"
|
|
HorizontalAlignment="Center"/>
|
|
</StackPanel>
|
|
</TabItem.Header>
|
|
<Grid RowDefinitions="Auto,*,Auto,Auto" Margin="4">
|
|
<!-- Column headers — desktop only -->
|
|
<Grid Grid.Row="0" ColumnDefinitions="180,*" Margin="12,4"
|
|
IsVisible="{Binding IsDesktop}">
|
|
<TextBlock Grid.Column="0" Text="{Binding Loc[contacts.name]}" FontWeight="Bold"/>
|
|
<TextBlock Grid.Column="1" Text="{Binding Loc[contacts.address]}" FontWeight="Bold"/>
|
|
</Grid>
|
|
<!-- Contacts list -->
|
|
<ListBox Grid.Row="1" ItemsSource="{Binding Contacts}"
|
|
SelectedItem="{Binding SelectedContactInList}">
|
|
<ListBox.ItemTemplate>
|
|
<DataTemplate x:DataType="vm:ContactEntry">
|
|
<Panel>
|
|
<!-- Desktop: 2 columns -->
|
|
<Grid ColumnDefinitions="180,*"
|
|
IsVisible="{Binding $parent[UserControl].((vm:MainWindowViewModel)DataContext).IsDesktop}">
|
|
<TextBlock Grid.Column="0" Text="{Binding Name}"
|
|
VerticalAlignment="Center"/>
|
|
<SelectableTextBlock Grid.Column="1" Text="{Binding Address}"
|
|
FontFamily="monospace" FontSize="12"
|
|
VerticalAlignment="Center"/>
|
|
</Grid>
|
|
<!-- Mobile: vertical card -->
|
|
<StackPanel Spacing="1" Margin="0,3"
|
|
IsVisible="{Binding $parent[UserControl].((vm:MainWindowViewModel)DataContext).IsMobile}">
|
|
<TextBlock Text="{Binding Name}" FontWeight="SemiBold" FontSize="13"
|
|
TextTrimming="CharacterEllipsis"/>
|
|
<SelectableTextBlock Text="{Binding Address}"
|
|
FontFamily="monospace" FontSize="11"
|
|
TextTrimming="CharacterEllipsis"/>
|
|
</StackPanel>
|
|
</Panel>
|
|
</DataTemplate>
|
|
</ListBox.ItemTemplate>
|
|
</ListBox>
|
|
<!-- Remove selected button -->
|
|
<Button Grid.Row="2" Content="{Binding Loc[contacts.remove]}"
|
|
Command="{Binding RemoveSelectedContactCommand}"
|
|
IsEnabled="{Binding SelectedContactInList, Converter={x:Static ObjectConverters.IsNotNull}}"
|
|
Margin="0,6,0,0"/>
|
|
<!-- Add contact form — Desktop: 3 columns -->
|
|
<Grid Grid.Row="3" ColumnDefinitions="180,*,Auto" Margin="0,8,0,0"
|
|
IsVisible="{Binding IsDesktop}">
|
|
<TextBox Grid.Column="0" PlaceholderText="{Binding Loc[contacts.name.ph]}"
|
|
Text="{Binding NewContactName}" Margin="0,0,6,0"/>
|
|
<TextBox Grid.Column="1" PlaceholderText="{Binding Loc[contacts.address.ph]}"
|
|
Text="{Binding NewContactAddress}" FontFamily="monospace"
|
|
Margin="0,0,6,0"/>
|
|
<Button Grid.Column="2" Content="{Binding Loc[contacts.add]}"
|
|
Command="{Binding AddContactCommand}"/>
|
|
</Grid>
|
|
<!-- Add contact form — Mobile: vertical -->
|
|
<StackPanel Grid.Row="3" Spacing="6" Margin="0,8,0,0"
|
|
IsVisible="{Binding IsMobile}">
|
|
<TextBox PlaceholderText="{Binding Loc[contacts.name.ph]}"
|
|
Text="{Binding NewContactName}"/>
|
|
<TextBox PlaceholderText="{Binding Loc[contacts.address.ph]}"
|
|
Text="{Binding NewContactAddress}" FontFamily="monospace"/>
|
|
<Button Content="{Binding Loc[contacts.add]}"
|
|
Command="{Binding AddContactCommand}"
|
|
HorizontalAlignment="Stretch"
|
|
HorizontalContentAlignment="Center"/>
|
|
</StackPanel>
|
|
</Grid>
|
|
</TabItem>
|
|
|
|
</TabControl>
|
|
|
|
</Grid>
|
|
|
|
<!-- Status bar: message on the left, connection status on the right.
|
|
The connection status is tappable and opens the server settings. -->
|
|
<Border Grid.Row="2" Background="{DynamicResource SurfaceBrush}"
|
|
BorderBrush="{DynamicResource BorderSubtleBrush}" BorderThickness="0,1,0,0"
|
|
Padding="12,7">
|
|
<Grid ColumnDefinitions="*,Auto">
|
|
<TextBlock Grid.Column="0" Text="{Binding StatusMessage}" FontSize="12"
|
|
TextWrapping="Wrap" VerticalAlignment="Center"/>
|
|
<StackPanel Grid.Column="1" Orientation="Horizontal" Spacing="6"
|
|
Margin="12,0,0,0" VerticalAlignment="Center"
|
|
Cursor="Hand" Background="Transparent"
|
|
ToolTip.Tip="{Binding Loc[server.title]}"
|
|
Tapped="OnConnectionStatusTapped">
|
|
<Ellipse Width="10" Height="10" Fill="{DynamicResource SuccessBrush}" VerticalAlignment="Center"
|
|
IsVisible="{Binding IsConnected}"/>
|
|
<Ellipse Width="10" Height="10" Fill="{DynamicResource DangerBrush}" VerticalAlignment="Center"
|
|
IsVisible="{Binding !IsConnected}"/>
|
|
<TextBlock Text="{Binding ConnectionStatusShort}" FontSize="12"
|
|
Foreground="{DynamicResource SystemAccentColor}"
|
|
VerticalAlignment="Center"/>
|
|
</StackPanel>
|
|
</Grid>
|
|
</Border>
|
|
|
|
<!-- ============ ADDRESS DETAIL OVERLAY ============ -->
|
|
<!-- In-app overlay instead of a separate Window: instant open/close
|
|
(no top-level window create/destroy). -->
|
|
<Border Grid.Row="0" Grid.RowSpan="3"
|
|
Background="{DynamicResource ScrimBrush}"
|
|
Tapped="OnAddressOverlayBackdropTapped"
|
|
IsVisible="{Binding AddressInfo, Converter={x:Static ObjectConverters.IsNotNull}}">
|
|
<Border Background="{DynamicResource OverlayCardBrush}"
|
|
BorderBrush="{DynamicResource BorderSubtleBrush}" BorderThickness="1" CornerRadius="8"
|
|
MaxWidth="540" Margin="16"
|
|
HorizontalAlignment="Center" VerticalAlignment="Center"
|
|
DataContext="{Binding AddressInfo}">
|
|
<ScrollViewer MaxHeight="640">
|
|
<StackPanel Margin="24" Spacing="16">
|
|
<TextBlock Text="{Binding Loc[addr.info.title]}"
|
|
FontSize="18" FontWeight="Bold"/>
|
|
|
|
<!-- Address -->
|
|
<StackPanel Spacing="4">
|
|
<TextBlock Text="{Binding Loc[addr.address]}" FontSize="11" Foreground="{DynamicResource TextSecondaryBrush}"/>
|
|
<SelectableTextBlock Text="{Binding Address}"
|
|
FontFamily="monospace" FontSize="13"
|
|
TextWrapping="Wrap"/>
|
|
</StackPanel>
|
|
|
|
<!-- Derivation path -->
|
|
<StackPanel Spacing="4">
|
|
<TextBlock Text="{Binding Loc[addr.derivpath]}" FontSize="11" Foreground="{DynamicResource TextSecondaryBrush}"/>
|
|
<SelectableTextBlock Text="{Binding DerivPath}"
|
|
FontFamily="monospace" FontSize="13"/>
|
|
</StackPanel>
|
|
|
|
<!-- Public key -->
|
|
<StackPanel Spacing="4">
|
|
<TextBlock Text="{Binding Loc[addr.pubkey]}" FontSize="11" Foreground="{DynamicResource TextSecondaryBrush}"/>
|
|
<SelectableTextBlock Text="{Binding PubKey}"
|
|
FontFamily="monospace" FontSize="12"
|
|
TextWrapping="Wrap"/>
|
|
</StackPanel>
|
|
|
|
<!-- Private key (only when available) -->
|
|
<StackPanel Spacing="8" IsVisible="{Binding HasPrivKey}">
|
|
<TextBlock Text="{Binding Loc[addr.privkey]}" FontSize="11"
|
|
Foreground="{DynamicResource DangerBrush}"/>
|
|
|
|
<!-- Not yet revealed: single reveal button -->
|
|
<Button IsVisible="{Binding !$parent[UserControl].((vm:MainWindowViewModel)DataContext).IsAddressPrivKeyRevealed}"
|
|
Content="{Binding Loc[walletinfo.seed.reveal]}"
|
|
Command="{Binding $parent[UserControl].((vm:MainWindowViewModel)DataContext).RequestPrivKeyRevealCommand}"/>
|
|
|
|
<!-- Revealed: key text + hide button -->
|
|
<StackPanel IsVisible="{Binding $parent[UserControl].((vm:MainWindowViewModel)DataContext).IsAddressPrivKeyRevealed}"
|
|
Spacing="6">
|
|
<SelectableTextBlock Text="{Binding PrivKey}"
|
|
FontFamily="monospace" FontSize="12"
|
|
Foreground="{DynamicResource DangerBrush}"
|
|
TextWrapping="Wrap"/>
|
|
<Button Content="{Binding Loc[walletinfo.seed.hide]}"
|
|
Command="{Binding $parent[UserControl].((vm:MainWindowViewModel)DataContext).HideAddressPrivKeyCommand}"/>
|
|
</StackPanel>
|
|
</StackPanel>
|
|
|
|
<Button Content="{Binding Loc[addr.close]}"
|
|
HorizontalAlignment="Right"
|
|
Command="{Binding $parent[UserControl].((vm:MainWindowViewModel)DataContext).CloseAddressInfoCommand}"/>
|
|
</StackPanel>
|
|
</ScrollViewer>
|
|
</Border>
|
|
</Border>
|
|
|
|
<!-- ============ PRIVATE KEY PASSWORD PROMPT ============ -->
|
|
<!-- Appears on top of the address detail overlay when the wallet is encrypted. -->
|
|
<Border Grid.Row="0" Grid.RowSpan="3"
|
|
Background="{DynamicResource ScrimBrush}"
|
|
IsVisible="{Binding IsPrivKeyPromptOpen}">
|
|
<Border Background="{DynamicResource OverlayCardBrush}"
|
|
BorderBrush="{DynamicResource BorderSubtleBrush}" BorderThickness="1" CornerRadius="8"
|
|
MaxWidth="360" Margin="16"
|
|
HorizontalAlignment="Center" VerticalAlignment="Center">
|
|
<StackPanel Margin="24" Spacing="14">
|
|
<TextBlock Text="{Binding Loc[addr.privkey.prompt.title]}"
|
|
FontSize="16" FontWeight="Bold"/>
|
|
<TextBlock Text="{Binding Loc[addr.privkey.prompt.desc]}"
|
|
FontSize="12" TextWrapping="Wrap"
|
|
Foreground="{DynamicResource TextSecondaryBrush}"/>
|
|
<TextBox Text="{Binding PrivKeyPromptPassword}"
|
|
PasswordChar="●"
|
|
PlaceholderText="{Binding Loc[wiz.open.placeholder]}"/>
|
|
<TextBlock Text="{Binding PrivKeyPromptError}"
|
|
Foreground="{DynamicResource DangerBrush}" FontSize="12"
|
|
IsVisible="{Binding PrivKeyPromptError,
|
|
Converter={x:Static StringConverters.IsNotNullOrEmpty}}"/>
|
|
<StackPanel Orientation="Horizontal" Spacing="8" HorizontalAlignment="Right">
|
|
<Button Content="{Binding Loc[addr.close]}"
|
|
Command="{Binding CancelPrivKeyPromptCommand}"/>
|
|
<Button Content="{Binding Loc[walletinfo.seed.reveal]}" Classes="accent"
|
|
Command="{Binding ConfirmPrivKeyPasswordCommand}"/>
|
|
</StackPanel>
|
|
</StackPanel>
|
|
</Border>
|
|
</Border>
|
|
|
|
<!-- ============ TRANSACTION DETAIL OVERLAY ============ -->
|
|
<!-- In-app overlay (like the address overlay): appears immediately with a
|
|
spinner; data arrives from the server in the background; instant close. -->
|
|
<Border Grid.Row="0" Grid.RowSpan="3"
|
|
Background="{DynamicResource ScrimBrush}"
|
|
Tapped="OnTxDetailsOverlayBackdropTapped"
|
|
IsVisible="{Binding IsTxDetailsOpen}">
|
|
<Border Background="{DynamicResource OverlayCardBrush}"
|
|
BorderBrush="{DynamicResource BorderSubtleBrush}" BorderThickness="1" CornerRadius="8"
|
|
MaxWidth="660" MaxHeight="800" Margin="16" Padding="0"
|
|
HorizontalAlignment="Center" VerticalAlignment="Center">
|
|
<Panel Margin="24">
|
|
|
|
<!-- Loading -->
|
|
<StackPanel IsVisible="{Binding IsTxDetailsLoading}"
|
|
HorizontalAlignment="Center" VerticalAlignment="Center" Spacing="14">
|
|
<ProgressBar IsIndeterminate="True" Width="220"/>
|
|
<TextBlock Text="{Binding Loc[tx.loading]}" Foreground="{DynamicResource TextSecondaryBrush}"
|
|
HorizontalAlignment="Center"/>
|
|
</StackPanel>
|
|
|
|
<!-- Content (IsVisible on the outer container so it stays bound
|
|
to the main VM; the inner DataContext is TxDetails) -->
|
|
<Grid IsVisible="{Binding !IsTxDetailsLoading}">
|
|
<DockPanel DataContext="{Binding TxDetails}">
|
|
<TextBlock DockPanel.Dock="Top" Text="{Binding Loc[tx.title]}"
|
|
FontSize="18" FontWeight="Bold" Margin="0,0,0,12"/>
|
|
|
|
<Button DockPanel.Dock="Bottom" Content="{Binding Loc[tx.close]}"
|
|
HorizontalAlignment="Right" Margin="0,12,0,0"
|
|
Command="{Binding $parent[UserControl].((vm:MainWindowViewModel)DataContext).CloseTransactionDetailsCommand}"/>
|
|
|
|
<ScrollViewer>
|
|
<StackPanel Spacing="18">
|
|
|
|
<!-- Header: net amount highlighted + status/SPV badges -->
|
|
<StackPanel Spacing="10">
|
|
<TextBlock Text="{Binding AmountHeader}" Classes="label"/>
|
|
<SelectableTextBlock Text="{Binding NetText}"
|
|
FontFamily="monospace" FontFeatures="+tnum"
|
|
FontSize="28" FontWeight="Bold"/>
|
|
<WrapPanel>
|
|
<!-- Coinbase badge: coins generated by mining (no sender) -->
|
|
<Border Classes="chip" Margin="0,0,8,6" IsVisible="{Binding IsCoinbase}"
|
|
Background="{DynamicResource WarningBrush}">
|
|
<StackPanel Orientation="Horizontal" Spacing="6">
|
|
<Viewbox Width="14" Height="14" VerticalAlignment="Center">
|
|
<Canvas Width="24" Height="24">
|
|
<Path Fill="#FFFFFF"
|
|
Data="M21,16.5C21,16.88 20.79,17.21 20.47,17.38L12.57,21.82C12.41,21.94 12.21,22 12,22C11.79,22 11.59,21.94 11.43,21.82L3.53,17.38C3.21,17.21 3,16.88 3,16.5V7.5C3,7.12 3.21,6.79 3.53,6.62L11.43,2.18C11.59,2.06 11.79,2 12,2C12.21,2 12.41,2.06 12.57,2.18L20.47,6.62C20.79,6.79 21,7.12 21,7.5V16.5M12,4.15L6.04,7.5L12,10.85L17.96,7.5L12,4.15M5,15.91L11,19.29V12.58L5,9.21V15.91M19,15.91V9.21L13,12.58V19.29L19,15.91Z"/>
|
|
</Canvas>
|
|
</Viewbox>
|
|
<TextBlock Text="{Binding Loc[tx.coinbase]}"
|
|
Foreground="#FFFFFF"
|
|
FontSize="12" FontWeight="SemiBold" VerticalAlignment="Center"/>
|
|
</StackPanel>
|
|
</Border>
|
|
<Border Classes="chip" Margin="0,0,8,6">
|
|
<TextBlock Text="{Binding StatusText}" FontSize="12"
|
|
Foreground="{DynamicResource TextSecondaryBrush}"/>
|
|
</Border>
|
|
</WrapPanel>
|
|
</StackPanel>
|
|
|
|
<!-- Section: Overview -->
|
|
<TextBlock Classes="section" Text="{Binding Loc[tx.sect.overview]}"/>
|
|
<Border Classes="card" Padding="16,12">
|
|
<StackPanel Spacing="10">
|
|
<Grid ColumnDefinitions="150,*">
|
|
<TextBlock Grid.Column="0" Classes="label" Text="{Binding Loc[tx.date]}"/>
|
|
<SelectableTextBlock Grid.Column="1" FontSize="13" Text="{Binding DateText}"/>
|
|
</Grid>
|
|
<Grid ColumnDefinitions="150,*">
|
|
<TextBlock Grid.Column="0" Classes="label" Text="{Binding CounterpartyHeader}"/>
|
|
<SelectableTextBlock Grid.Column="1" FontSize="13" Classes="mono"
|
|
TextWrapping="Wrap" Text="{Binding CounterpartyText}"/>
|
|
</Grid>
|
|
</StackPanel>
|
|
</Border>
|
|
|
|
<!-- Section: Amounts and fees -->
|
|
<TextBlock Classes="section" Text="{Binding Loc[tx.sect.amounts]}"/>
|
|
<Border Classes="card" Padding="16,12">
|
|
<StackPanel Spacing="10">
|
|
<Grid ColumnDefinitions="150,*">
|
|
<TextBlock Grid.Column="0" Classes="label" Text="{Binding AmountHeader}"/>
|
|
<SelectableTextBlock Grid.Column="1" FontSize="13" Classes="mono" Text="{Binding AmountText}"/>
|
|
</Grid>
|
|
<Grid ColumnDefinitions="150,*">
|
|
<TextBlock Grid.Column="0" Classes="label" Text="{Binding Loc[tx.fee]}"/>
|
|
<SelectableTextBlock Grid.Column="1" FontSize="13" Classes="mono" Text="{Binding FeeText}"/>
|
|
</Grid>
|
|
<Grid ColumnDefinitions="150,*">
|
|
<TextBlock Grid.Column="0" Classes="label" Text="{Binding Loc[tx.feerate]}"/>
|
|
<SelectableTextBlock Grid.Column="1" FontSize="13" Classes="mono" Text="{Binding FeeRateText}"/>
|
|
</Grid>
|
|
<Border Height="1" Background="{DynamicResource BorderSubtleBrush}" Margin="0,2"/>
|
|
<Grid ColumnDefinitions="150,*">
|
|
<TextBlock Grid.Column="0" Classes="label" Text="{Binding Loc[tx.net]}"/>
|
|
<SelectableTextBlock Grid.Column="1" FontSize="14" Classes="mono"
|
|
FontWeight="Bold" Text="{Binding NetText}"/>
|
|
</Grid>
|
|
</StackPanel>
|
|
</Border>
|
|
|
|
<!-- Section: Technical details -->
|
|
<TextBlock Classes="section" Text="{Binding Loc[tx.sect.tech]}"/>
|
|
<Border Classes="card" Padding="16,12">
|
|
<StackPanel Spacing="10">
|
|
<StackPanel Spacing="3">
|
|
<TextBlock Classes="label" Text="{Binding Loc[tx.id]}"/>
|
|
<SelectableTextBlock FontSize="12" Classes="mono"
|
|
TextWrapping="Wrap" Text="{Binding Txid}"/>
|
|
</StackPanel>
|
|
<Grid ColumnDefinitions="150,*">
|
|
<TextBlock Grid.Column="0" Classes="label" Text="{Binding Loc[tx.size.total]}"/>
|
|
<SelectableTextBlock Grid.Column="1" FontSize="13" Text="{Binding TotalSizeText}"/>
|
|
</Grid>
|
|
<Grid ColumnDefinitions="150,*">
|
|
<TextBlock Grid.Column="0" Classes="label" Text="{Binding Loc[tx.size.virtual]}"/>
|
|
<SelectableTextBlock Grid.Column="1" FontSize="13" Text="{Binding VirtualSizeText}"/>
|
|
</Grid>
|
|
<Grid ColumnDefinitions="150,*">
|
|
<TextBlock Grid.Column="0" Classes="label" Text="{Binding Loc[tx.rbf]}"/>
|
|
<SelectableTextBlock Grid.Column="1" FontSize="13" Text="{Binding RbfText}"/>
|
|
</Grid>
|
|
</StackPanel>
|
|
</Border>
|
|
|
|
<TextBlock Classes="section" Text="{Binding Loc[tx.inputs]}"/>
|
|
<Border Classes="card" Padding="14,4">
|
|
<ItemsControl ItemsSource="{Binding Inputs}">
|
|
<ItemsControl.ItemTemplate>
|
|
<DataTemplate x:DataType="vm:TxIoRow">
|
|
<!-- Two-line layout: txid ref on first line, address+amount on second -->
|
|
<StackPanel Margin="0,6,0,4">
|
|
<SelectableTextBlock Text="{Binding Position}"
|
|
FontFamily="monospace" FontSize="10"
|
|
Foreground="{DynamicResource TextMutedBrush}"
|
|
TextWrapping="Wrap"/>
|
|
<Grid ColumnDefinitions="*,Auto" Margin="0,2,0,0">
|
|
<SelectableTextBlock Grid.Column="0" Text="{Binding Address}"
|
|
FontFamily="monospace" FontSize="11"
|
|
TextWrapping="Wrap" VerticalAlignment="Top"
|
|
Foreground="{Binding IsMine, Converter={x:Static vm:MineColorConverter.Instance}}"/>
|
|
<SelectableTextBlock Grid.Column="1" Text="{Binding Amount}"
|
|
FontFamily="monospace" FontFeatures="+tnum" FontSize="11"
|
|
VerticalAlignment="Top" Margin="12,0,0,0"/>
|
|
</Grid>
|
|
</StackPanel>
|
|
</DataTemplate>
|
|
</ItemsControl.ItemTemplate>
|
|
</ItemsControl>
|
|
</Border>
|
|
|
|
<TextBlock Classes="section" Text="{Binding Loc[tx.outputs]}"/>
|
|
<Border Classes="card" Padding="14,4">
|
|
<ItemsControl ItemsSource="{Binding Outputs}">
|
|
<ItemsControl.ItemTemplate>
|
|
<DataTemplate x:DataType="vm:TxIoRow">
|
|
<Grid ColumnDefinitions="44,*,Auto" Margin="0,6">
|
|
<TextBlock Grid.Column="0" Text="{Binding Position}"
|
|
FontFamily="monospace" FontSize="11"
|
|
Foreground="{DynamicResource TextMutedBrush}"
|
|
VerticalAlignment="Top"/>
|
|
<SelectableTextBlock Grid.Column="1" Text="{Binding Address}"
|
|
FontFamily="monospace" FontSize="11"
|
|
TextWrapping="Wrap" VerticalAlignment="Top"
|
|
Foreground="{Binding IsMine, Converter={x:Static vm:MineColorConverter.Instance}}"/>
|
|
<SelectableTextBlock Grid.Column="2" Text="{Binding Amount}"
|
|
FontFamily="monospace" FontFeatures="+tnum" FontSize="11"
|
|
VerticalAlignment="Top" Margin="12,0,0,0"/>
|
|
</Grid>
|
|
</DataTemplate>
|
|
</ItemsControl.ItemTemplate>
|
|
</ItemsControl>
|
|
</Border>
|
|
|
|
</StackPanel>
|
|
</ScrollViewer>
|
|
</DockPanel>
|
|
</Grid>
|
|
</Panel>
|
|
</Border>
|
|
</Border>
|
|
|
|
<!-- ============ SERVER SETTINGS OVERLAY ============ -->
|
|
<!-- Same pattern as the address overlay: instant open/close.
|
|
Accessible from Settings → Server. -->
|
|
<Border Grid.Row="0" Grid.RowSpan="3"
|
|
Background="{DynamicResource ScrimBrush}"
|
|
Tapped="OnServerOverlayBackdropTapped"
|
|
IsVisible="{Binding IsServerSettingsOpen}">
|
|
<Border Background="{DynamicResource OverlayCardBrush}"
|
|
BorderBrush="{DynamicResource BorderSubtleBrush}" BorderThickness="1"
|
|
Classes.desktop-overlay="{Binding IsDesktop}">
|
|
<ScrollViewer>
|
|
<StackPanel Margin="24" Spacing="14">
|
|
<TextBlock Text="{Binding Loc[server.title]}"
|
|
FontSize="18" FontWeight="Bold"/>
|
|
|
|
<!-- Host + port — Desktop: 2 columns -->
|
|
<Grid ColumnDefinitions="*,Auto" RowDefinitions="Auto,Auto"
|
|
IsVisible="{Binding IsDesktop}">
|
|
<TextBlock Grid.Row="0" Grid.Column="0" Text="{Binding Loc[server.host]}"
|
|
FontSize="11" Foreground="{DynamicResource TextSecondaryBrush}"/>
|
|
<TextBlock Grid.Row="0" Grid.Column="1" Text="{Binding Loc[server.port]}"
|
|
FontSize="11" Foreground="{DynamicResource TextSecondaryBrush}" Margin="10,0,0,0" Width="90"/>
|
|
<TextBox Grid.Row="1" Grid.Column="0" Text="{Binding ServerHost}"
|
|
FontFamily="monospace" Margin="0,2,0,0"/>
|
|
<TextBox Grid.Row="1" Grid.Column="1" Text="{Binding ServerPort}"
|
|
FontFamily="monospace" Width="90" Margin="10,2,0,0"/>
|
|
</Grid>
|
|
<!-- Host + port — Mobile: vertical, larger font -->
|
|
<StackPanel Spacing="10" IsVisible="{Binding IsMobile}">
|
|
<StackPanel Spacing="4">
|
|
<TextBlock Text="{Binding Loc[server.host]}" FontSize="13" Foreground="{DynamicResource TextSecondaryBrush}"/>
|
|
<TextBox Text="{Binding ServerHost}" FontFamily="monospace" FontSize="15"/>
|
|
</StackPanel>
|
|
<StackPanel Spacing="4">
|
|
<TextBlock Text="{Binding Loc[server.port]}" FontSize="13" Foreground="{DynamicResource TextSecondaryBrush}"/>
|
|
<TextBox Text="{Binding ServerPort}" FontFamily="monospace" FontSize="15"/>
|
|
</StackPanel>
|
|
</StackPanel>
|
|
|
|
<!-- Actions — Desktop: in a row -->
|
|
<StackPanel Orientation="Horizontal" Spacing="8" IsVisible="{Binding IsDesktop}">
|
|
<Button Content="{Binding Loc[wallet.connect]}" Classes="accent"
|
|
Command="{Binding ConnectAndSyncCommand}"/>
|
|
<Button Content="{Binding Loc[wallet.discover]}"
|
|
Command="{Binding DiscoverServersCommand}"/>
|
|
<Button Content="{Binding Loc[wallet.resetcert]}"
|
|
Command="{Binding ResetCertificatesCommand}"/>
|
|
</StackPanel>
|
|
<!-- Actions — Mobile: stacked -->
|
|
<StackPanel Spacing="6" IsVisible="{Binding IsMobile}">
|
|
<Button Content="{Binding Loc[wallet.connect]}" Classes="accent"
|
|
Command="{Binding ConnectAndSyncCommand}"
|
|
HorizontalAlignment="Stretch" HorizontalContentAlignment="Center"/>
|
|
<Button Content="{Binding Loc[wallet.discover]}"
|
|
Command="{Binding DiscoverServersCommand}"
|
|
HorizontalAlignment="Stretch" HorizontalContentAlignment="Center"/>
|
|
<Button Content="{Binding Loc[wallet.resetcert]}"
|
|
Command="{Binding ResetCertificatesCommand}"
|
|
HorizontalAlignment="Stretch" HorizontalContentAlignment="Center"/>
|
|
</StackPanel>
|
|
|
|
<!-- Connection status -->
|
|
<TextBlock Text="{Binding ConnectionStatus}" Foreground="{DynamicResource TextSecondaryBrush}"/>
|
|
|
|
<!-- Known servers: click to populate host/port -->
|
|
<TextBlock Text="{Binding Loc[server.known]}" FontSize="11" Foreground="{DynamicResource TextSecondaryBrush}"/>
|
|
<ListBox ItemsSource="{Binding KnownServers}"
|
|
SelectedItem="{Binding SelectedKnownServer}"
|
|
MaxHeight="300">
|
|
<ListBox.Styles>
|
|
<Style Selector="ListBox:empty">
|
|
<Setter Property="Template">
|
|
<ControlTemplate>
|
|
<TextBlock Text="{Binding Loc[server.empty]}"
|
|
Foreground="{DynamicResource TextSecondaryBrush}" FontSize="12"
|
|
TextWrapping="Wrap" Margin="8"/>
|
|
</ControlTemplate>
|
|
</Setter>
|
|
</Style>
|
|
</ListBox.Styles>
|
|
<ListBox.ItemTemplate>
|
|
<DataTemplate x:DataType="net:KnownServer">
|
|
<Panel>
|
|
<!-- Desktop: host + ports in 2 columns -->
|
|
<Grid ColumnDefinitions="*,Auto"
|
|
IsVisible="{Binding $parent[UserControl].((vm:MainWindowViewModel)DataContext).IsDesktop}">
|
|
<TextBlock Grid.Column="0" Text="{Binding Host}"
|
|
FontFamily="monospace" FontSize="13"
|
|
VerticalAlignment="Center"/>
|
|
<TextBlock Grid.Column="1" FontSize="11" Foreground="{DynamicResource TextSecondaryBrush}"
|
|
VerticalAlignment="Center">
|
|
<Run Text="tcp "/><Run Text="{Binding TcpPort}"/>
|
|
<Run Text=" ssl "/><Run Text="{Binding SslPort}"/>
|
|
</TextBlock>
|
|
</Grid>
|
|
<!-- Mobile: host above, ports below -->
|
|
<StackPanel Spacing="2" Margin="0,4"
|
|
IsVisible="{Binding $parent[UserControl].((vm:MainWindowViewModel)DataContext).IsMobile}">
|
|
<TextBlock Text="{Binding Host}"
|
|
FontFamily="monospace" FontSize="15"
|
|
TextTrimming="CharacterEllipsis"/>
|
|
<StackPanel Orientation="Horizontal" Spacing="16">
|
|
<TextBlock FontSize="12" Foreground="{DynamicResource TextSecondaryBrush}">
|
|
<Run Text="tcp "/><Run Text="{Binding TcpPort}"/>
|
|
</TextBlock>
|
|
<TextBlock FontSize="12" Foreground="{DynamicResource TextSecondaryBrush}">
|
|
<Run Text="ssl "/><Run Text="{Binding SslPort}"/>
|
|
</TextBlock>
|
|
</StackPanel>
|
|
</StackPanel>
|
|
</Panel>
|
|
</DataTemplate>
|
|
</ListBox.ItemTemplate>
|
|
</ListBox>
|
|
|
|
<Button Content="{Binding Loc[addr.close]}"
|
|
HorizontalAlignment="Right"
|
|
Command="{Binding CloseServerSettingsCommand}"/>
|
|
</StackPanel>
|
|
</ScrollViewer>
|
|
</Border>
|
|
</Border>
|
|
|
|
<!-- ============ WALLET INFO OVERLAY ============ -->
|
|
<Border Grid.Row="0" Grid.RowSpan="3"
|
|
Background="{DynamicResource ScrimBrush}"
|
|
Tapped="OnWalletInfoOverlayBackdropTapped"
|
|
IsVisible="{Binding IsWalletInfoOpen}">
|
|
<Border Background="{DynamicResource OverlayCardBrush}"
|
|
BorderBrush="{DynamicResource BorderSubtleBrush}" BorderThickness="1" CornerRadius="8"
|
|
MaxWidth="500" Margin="16"
|
|
HorizontalAlignment="Center" VerticalAlignment="Center">
|
|
<ScrollViewer MaxHeight="620">
|
|
<StackPanel Margin="24" Spacing="14">
|
|
<TextBlock Text="{Binding Loc[walletinfo.title]}"
|
|
FontSize="18" FontWeight="Bold"/>
|
|
|
|
<!-- File name -->
|
|
<StackPanel Spacing="3">
|
|
<TextBlock Text="{Binding Loc[walletinfo.file]}" FontSize="11"
|
|
Foreground="{DynamicResource TextSecondaryBrush}"/>
|
|
<SelectableTextBlock Text="{Binding WalletInfoFileName}"
|
|
FontFamily="monospace" FontSize="13"/>
|
|
</StackPanel>
|
|
|
|
<!-- Network -->
|
|
<StackPanel Spacing="3">
|
|
<TextBlock Text="{Binding Loc[walletinfo.network]}" FontSize="11"
|
|
Foreground="{DynamicResource TextSecondaryBrush}"/>
|
|
<TextBlock Text="{Binding WalletInfoNetwork}" FontSize="13"/>
|
|
</StackPanel>
|
|
|
|
<!-- Wallet type -->
|
|
<StackPanel Spacing="3">
|
|
<TextBlock Text="{Binding Loc[walletinfo.type]}" FontSize="11"
|
|
Foreground="{DynamicResource TextSecondaryBrush}"/>
|
|
<TextBlock Text="{Binding WalletInfoType}" FontSize="13"/>
|
|
</StackPanel>
|
|
|
|
<!-- Script kind -->
|
|
<StackPanel Spacing="3">
|
|
<TextBlock Text="{Binding Loc[walletinfo.script]}" FontSize="11"
|
|
Foreground="{DynamicResource TextSecondaryBrush}"/>
|
|
<TextBlock Text="{Binding WalletInfoScriptKind}" FontSize="13"/>
|
|
</StackPanel>
|
|
|
|
<!-- Derivation path (only if present) -->
|
|
<StackPanel Spacing="3"
|
|
IsVisible="{Binding WalletInfoDerivPath,
|
|
Converter={x:Static StringConverters.IsNotNullOrEmpty}}">
|
|
<TextBlock Text="{Binding Loc[walletinfo.derivpath]}" FontSize="11"
|
|
Foreground="{DynamicResource TextSecondaryBrush}"/>
|
|
<SelectableTextBlock Text="{Binding WalletInfoDerivPath}"
|
|
FontFamily="monospace" FontSize="13"/>
|
|
</StackPanel>
|
|
|
|
<!-- Master fingerprint (only if present) -->
|
|
<StackPanel Spacing="3"
|
|
IsVisible="{Binding WalletInfoFingerprint,
|
|
Converter={x:Static StringConverters.IsNotNullOrEmpty}}">
|
|
<TextBlock Text="{Binding Loc[walletinfo.fingerprint]}" FontSize="11"
|
|
Foreground="{DynamicResource TextSecondaryBrush}"/>
|
|
<SelectableTextBlock Text="{Binding WalletInfoFingerprint}"
|
|
FontFamily="monospace" FontSize="13"/>
|
|
</StackPanel>
|
|
|
|
<!-- Account xpub (only if present) -->
|
|
<StackPanel Spacing="3"
|
|
IsVisible="{Binding WalletInfoXpub,
|
|
Converter={x:Static StringConverters.IsNotNullOrEmpty}}">
|
|
<TextBlock Text="{Binding Loc[walletinfo.xpub]}" FontSize="11"
|
|
Foreground="{DynamicResource TextSecondaryBrush}"/>
|
|
<SelectableTextBlock Text="{Binding WalletInfoXpub}"
|
|
FontFamily="monospace" FontSize="11"
|
|
TextWrapping="Wrap"/>
|
|
</StackPanel>
|
|
|
|
<!-- BIP39 passphrase indicator -->
|
|
<StackPanel Spacing="3" IsVisible="{Binding WalletInfoHasPassphrase}">
|
|
<TextBlock Text="{Binding Loc[walletinfo.passphrase]}" FontSize="11"
|
|
Foreground="{DynamicResource TextSecondaryBrush}"/>
|
|
<TextBlock Text="{Binding Loc[walletinfo.passphrase.set]}"
|
|
FontSize="13" Foreground="{DynamicResource TextSecondaryBrush}"/>
|
|
</StackPanel>
|
|
|
|
<!-- Separator -->
|
|
<Border Height="1" Background="{DynamicResource BorderSubtleBrush}" Margin="0,4"/>
|
|
|
|
<!-- Seed section -->
|
|
<TextBlock Text="{Binding Loc[walletinfo.seed.section]}"
|
|
FontSize="13" FontWeight="SemiBold"/>
|
|
|
|
<!-- No seed wallet -->
|
|
<TextBlock IsVisible="{Binding !WalletInfoHasSeed}"
|
|
Text="{Binding Loc[walletinfo.seed.noseed]}"
|
|
Foreground="{DynamicResource TextSecondaryBrush}"
|
|
FontSize="12" TextWrapping="Wrap"/>
|
|
|
|
<!-- Seed wallet: needs password -->
|
|
<StackPanel IsVisible="{Binding WalletInfoHasSeed}" Spacing="10">
|
|
|
|
<!-- Not yet revealed + password needed -->
|
|
<StackPanel IsVisible="{Binding WalletInfoSeedNeedsPassword}" Spacing="8">
|
|
<StackPanel IsVisible="{Binding !IsWalletInfoSeedRevealed}" Spacing="8">
|
|
<TextBlock Text="{Binding Loc[walletinfo.seed.password]}"
|
|
FontSize="12" TextWrapping="Wrap"
|
|
Foreground="{DynamicResource TextSecondaryBrush}"/>
|
|
<TextBox Text="{Binding WalletInfoSeedPasswordInput}"
|
|
PasswordChar="●"
|
|
PlaceholderText="{Binding Loc[wiz.open.placeholder]}"/>
|
|
<TextBlock Text="{Binding WalletInfoSeedError}"
|
|
Foreground="{DynamicResource DangerBrush}" FontSize="12"
|
|
IsVisible="{Binding WalletInfoSeedError,
|
|
Converter={x:Static StringConverters.IsNotNullOrEmpty}}"/>
|
|
<Button Content="{Binding Loc[walletinfo.seed.reveal]}"
|
|
Command="{Binding RevealSeedCommand}"/>
|
|
</StackPanel>
|
|
</StackPanel>
|
|
|
|
<!-- Not yet revealed + no password needed -->
|
|
<Button IsVisible="{Binding !WalletInfoSeedNeedsPassword}"
|
|
Content="{Binding Loc[walletinfo.seed.reveal]}"
|
|
Command="{Binding RevealSeedCommand}"
|
|
IsEnabled="{Binding !IsWalletInfoSeedRevealed}"/>
|
|
|
|
<!-- Revealed seed -->
|
|
<StackPanel IsVisible="{Binding IsWalletInfoSeedRevealed}" Spacing="8">
|
|
<Border BorderBrush="{DynamicResource DangerBrush}" BorderThickness="1"
|
|
CornerRadius="6" Padding="14"
|
|
Background="{DynamicResource SurfaceAltBrush}">
|
|
<SelectableTextBlock Text="{Binding WalletInfoSeedText}"
|
|
FontFamily="monospace" FontSize="15"
|
|
TextWrapping="Wrap"/>
|
|
</Border>
|
|
<TextBlock Text="{Binding Loc[walletinfo.seed.warning]}"
|
|
Foreground="{DynamicResource DangerBrush}"
|
|
FontSize="12" TextWrapping="Wrap"/>
|
|
<Button Content="{Binding Loc[walletinfo.seed.hide]}"
|
|
Command="{Binding HideSeedCommand}"/>
|
|
</StackPanel>
|
|
|
|
</StackPanel>
|
|
|
|
<Button Content="{Binding Loc[addr.close]}"
|
|
HorizontalAlignment="Right"
|
|
Command="{Binding CloseWalletInfoCommand}"/>
|
|
</StackPanel>
|
|
</ScrollViewer>
|
|
</Border>
|
|
</Border>
|
|
|
|
<!-- ============ SETTINGS OVERLAY ============ -->
|
|
<!-- In-app instead of nested submenus: avoids slow OS popups on WSLg. -->
|
|
<Border Grid.Row="0" Grid.RowSpan="3"
|
|
Background="{DynamicResource ScrimBrush}"
|
|
Tapped="OnSettingsOverlayBackdropTapped"
|
|
IsVisible="{Binding IsSettingsOpen}">
|
|
<Border Background="{DynamicResource OverlayCardBrush}"
|
|
BorderBrush="{DynamicResource BorderSubtleBrush}" BorderThickness="1" CornerRadius="8"
|
|
MaxWidth="440" Margin="16"
|
|
HorizontalAlignment="Center" VerticalAlignment="Center">
|
|
<ScrollViewer MaxHeight="640">
|
|
<StackPanel Margin="24" Spacing="16">
|
|
<TextBlock Text="{Binding Loc[settings.title]}"
|
|
FontSize="18" FontWeight="Bold"/>
|
|
|
|
<!-- Language -->
|
|
<StackPanel Spacing="6">
|
|
<TextBlock Text="{Binding Loc[settings.language]}" FontSize="11" Foreground="{DynamicResource TextSecondaryBrush}"/>
|
|
<WrapPanel>
|
|
<RadioButton GroupName="lang" Content="Italiano" Margin="0,0,14,4"
|
|
IsChecked="{Binding IsLangIt, Mode=OneWay}"
|
|
Command="{Binding SetLanguageCommand}" CommandParameter="it"/>
|
|
<RadioButton GroupName="lang" Content="English" Margin="0,0,14,4"
|
|
IsChecked="{Binding IsLangEn, Mode=OneWay}"
|
|
Command="{Binding SetLanguageCommand}" CommandParameter="en"/>
|
|
<RadioButton GroupName="lang" Content="Español" Margin="0,0,14,4"
|
|
IsChecked="{Binding IsLangEs, Mode=OneWay}"
|
|
Command="{Binding SetLanguageCommand}" CommandParameter="es"/>
|
|
<RadioButton GroupName="lang" Content="Français" Margin="0,0,14,4"
|
|
IsChecked="{Binding IsLangFr, Mode=OneWay}"
|
|
Command="{Binding SetLanguageCommand}" CommandParameter="fr"/>
|
|
<RadioButton GroupName="lang" Content="Português" Margin="0,0,14,4"
|
|
IsChecked="{Binding IsLangPt, Mode=OneWay}"
|
|
Command="{Binding SetLanguageCommand}" CommandParameter="pt"/>
|
|
<RadioButton GroupName="lang" Content="Deutsch" Margin="0,0,14,4"
|
|
IsChecked="{Binding IsLangDe, Mode=OneWay}"
|
|
Command="{Binding SetLanguageCommand}" CommandParameter="de"/>
|
|
</WrapPanel>
|
|
</StackPanel>
|
|
|
|
<!-- Unit -->
|
|
<StackPanel Spacing="6">
|
|
<TextBlock Text="{Binding Loc[settings.unit]}" FontSize="11" Foreground="{DynamicResource TextSecondaryBrush}"/>
|
|
<WrapPanel>
|
|
<RadioButton GroupName="unit" Content="PLM" Margin="0,0,14,4"
|
|
IsChecked="{Binding IsUnitPlm, Mode=OneWay}"
|
|
Command="{Binding SetUnitCommand}" CommandParameter="PLM"/>
|
|
<RadioButton GroupName="unit" Content="mPLM" Margin="0,0,14,4"
|
|
IsChecked="{Binding IsUnitMilli, Mode=OneWay}"
|
|
Command="{Binding SetUnitCommand}" CommandParameter="mPLM"/>
|
|
<RadioButton GroupName="unit" Content="µPLM" Margin="0,0,14,4"
|
|
IsChecked="{Binding IsUnitMicro, Mode=OneWay}"
|
|
Command="{Binding SetUnitCommand}" CommandParameter="µPLM"/>
|
|
<RadioButton GroupName="unit" Content="sat" Margin="0,0,14,4"
|
|
IsChecked="{Binding IsUnitSat, Mode=OneWay}"
|
|
Command="{Binding SetUnitCommand}" CommandParameter="sat"/>
|
|
</WrapPanel>
|
|
</StackPanel>
|
|
|
|
<!-- Indexing server (configurable even before a wallet is open) -->
|
|
<Button Content="{Binding Loc[settings.server]}"
|
|
HorizontalAlignment="Left"
|
|
Command="{Binding OpenServerSettingsCommand}"/>
|
|
|
|
<Button Content="{Binding Loc[addr.close]}"
|
|
HorizontalAlignment="Right"
|
|
Command="{Binding CloseSettingsCommand}"/>
|
|
</StackPanel>
|
|
</ScrollViewer>
|
|
</Border>
|
|
</Border>
|
|
|
|
<!-- ============ HELP / ABOUT OVERLAY ============ -->
|
|
<!-- Same pattern as the settings overlay: instant open/close. -->
|
|
<Border Grid.Row="0" Grid.RowSpan="3"
|
|
Background="{DynamicResource ScrimBrush}"
|
|
Tapped="OnHelpOverlayBackdropTapped"
|
|
IsVisible="{Binding IsHelpOpen}">
|
|
<Border Background="{DynamicResource OverlayCardBrush}"
|
|
BorderBrush="{DynamicResource BorderSubtleBrush}" BorderThickness="1" CornerRadius="8"
|
|
MaxWidth="440" Margin="16"
|
|
HorizontalAlignment="Stretch" VerticalAlignment="Center">
|
|
<StackPanel Margin="24" Spacing="16">
|
|
<TextBlock Text="{Binding Loc[help.title]}"
|
|
FontSize="18" FontWeight="Bold"/>
|
|
|
|
<!-- Fixed height so the overlay never resizes when switching tabs. -->
|
|
<TabControl Height="320">
|
|
<!-- Tab: Info -->
|
|
<TabItem Header="{Binding Loc[help.tab.info]}">
|
|
<ScrollViewer VerticalScrollBarVisibility="Auto">
|
|
<StackPanel Spacing="12" Margin="0,12,0,0">
|
|
<StackPanel Spacing="4">
|
|
<TextBlock Text="Palladium Wallet" FontSize="16" FontWeight="Bold"/>
|
|
<TextBlock Text="{Binding WindowTitle}" FontSize="12"
|
|
Foreground="{DynamicResource TextSecondaryBrush}"/>
|
|
</StackPanel>
|
|
<TextBlock Text="{Binding Loc[help.info]}" TextWrapping="Wrap"/>
|
|
<StackPanel Orientation="Horizontal" Spacing="8">
|
|
<Button Content="{Binding Loc[help.bug.report]}"
|
|
Click="OnOpenBugReportClick"
|
|
HorizontalAlignment="Left"/>
|
|
<Button Content="{Binding Loc[help.user.guide]}"
|
|
Click="OnOpenUserGuideClick"
|
|
HorizontalAlignment="Left"/>
|
|
</StackPanel>
|
|
<Border BorderBrush="{DynamicResource BorderSubtleBrush}"
|
|
BorderThickness="0,1,0,0" Margin="0,4,0,0"/>
|
|
<StackPanel Spacing="4">
|
|
<TextBlock Text="© 2026 Davide Grilli — MIT License"
|
|
FontSize="12"
|
|
Foreground="{DynamicResource TextSecondaryBrush}"/>
|
|
<TextBlock Text="Built with .NET 10 · Avalonia 12 · NBitcoin"
|
|
FontSize="11"
|
|
Foreground="{DynamicResource TextSecondaryBrush}"/>
|
|
</StackPanel>
|
|
</StackPanel>
|
|
</ScrollViewer>
|
|
</TabItem>
|
|
|
|
<!-- Tab: Donate -->
|
|
<TabItem Header="{Binding Loc[help.tab.donate]}">
|
|
<ScrollViewer VerticalScrollBarVisibility="Auto">
|
|
<StackPanel Spacing="12" Margin="0,12,0,0">
|
|
<TextBlock Text="{Binding Loc[donate.desc]}" TextWrapping="Wrap"
|
|
Foreground="{DynamicResource TextSecondaryBrush}"/>
|
|
|
|
<!-- Dev address (read-only) -->
|
|
<StackPanel Spacing="4">
|
|
<TextBlock Text="{Binding Loc[donate.dev.address]}" FontSize="11"
|
|
Foreground="{DynamicResource TextSecondaryBrush}"/>
|
|
<SelectableTextBlock Text="{x:Static vm:MainWindowViewModel.DevAddress}"
|
|
FontFamily="monospace" FontSize="11"
|
|
TextWrapping="Wrap"/>
|
|
</StackPanel>
|
|
|
|
<!-- Amount input -->
|
|
<StackPanel Spacing="4">
|
|
<TextBlock Text="{Binding Loc[donate.amount]}" FontSize="11"
|
|
Foreground="{DynamicResource TextSecondaryBrush}"/>
|
|
<Grid ColumnDefinitions="*,Auto">
|
|
<TextBox Grid.Column="0"
|
|
Text="{Binding DonateAmount}"
|
|
PlaceholderText="{Binding UnitLabel}"/>
|
|
<TextBlock Grid.Column="1" Text="{Binding UnitLabel}"
|
|
VerticalAlignment="Center" Margin="8,0,0,0"
|
|
Foreground="{DynamicResource TextSecondaryBrush}"/>
|
|
</Grid>
|
|
</StackPanel>
|
|
|
|
<!-- Preview -->
|
|
<SelectableTextBlock Text="{Binding DonatePreview}"
|
|
IsVisible="{Binding DonatePreview,
|
|
Converter={x:Static StringConverters.IsNotNullOrEmpty}}"
|
|
FontFamily="monospace" FontSize="11"
|
|
TextWrapping="Wrap"
|
|
Foreground="{DynamicResource TextSecondaryBrush}"/>
|
|
|
|
<!-- Buttons -->
|
|
<StackPanel Orientation="Horizontal" Spacing="8" HorizontalAlignment="Right">
|
|
<Button Content="{Binding Loc[donate.confirm]}"
|
|
Classes="accent"
|
|
IsEnabled="{Binding HasPendingDonate}"
|
|
Command="{Binding ConfirmDonateCommand}"/>
|
|
<Button Content="{Binding Loc[donate.prepare]}"
|
|
Command="{Binding PrepareDonateCommand}"/>
|
|
</StackPanel>
|
|
</StackPanel>
|
|
</ScrollViewer>
|
|
</TabItem>
|
|
</TabControl>
|
|
|
|
<Button Content="{Binding Loc[addr.close]}"
|
|
HorizontalAlignment="Right"
|
|
Command="{Binding CloseHelpCommand}"/>
|
|
</StackPanel>
|
|
</Border>
|
|
</Border>
|
|
|
|
<!-- ============ UPDATE AVAILABLE OVERLAY ============ -->
|
|
<!-- Same pattern as the help overlay: instant open/close. -->
|
|
<Border Grid.Row="0" Grid.RowSpan="3"
|
|
Background="{DynamicResource ScrimBrush}"
|
|
Tapped="OnUpdateAvailableOverlayBackdropTapped"
|
|
IsVisible="{Binding IsUpdateAvailableOpen}">
|
|
<Border Background="{DynamicResource OverlayCardBrush}"
|
|
BorderBrush="{DynamicResource BorderSubtleBrush}" BorderThickness="1" CornerRadius="8"
|
|
MaxWidth="440" Margin="16"
|
|
HorizontalAlignment="Center" VerticalAlignment="Center">
|
|
<StackPanel Margin="24" Spacing="16">
|
|
<TextBlock Text="{Binding Loc[update.title]}"
|
|
FontSize="18" FontWeight="Bold"/>
|
|
<TextBlock TextWrapping="Wrap">
|
|
<Run Text="{Binding Loc[update.message]}"/>
|
|
<Run Text=" "/>
|
|
<Run Text="{Binding UpdateAvailableTag}" FontWeight="Bold"/>
|
|
</TextBlock>
|
|
<StackPanel Orientation="Horizontal" Spacing="8" HorizontalAlignment="Right">
|
|
<Button Content="{Binding Loc[update.download]}"
|
|
Classes="accent"
|
|
Click="OnOpenReleasePageClick"/>
|
|
<Button Content="{Binding Loc[update.dismiss]}"
|
|
Command="{Binding CloseUpdateAvailableCommand}"/>
|
|
</StackPanel>
|
|
</StackPanel>
|
|
</Border>
|
|
</Border>
|
|
</Grid>
|
|
</UserControl>
|