refactor(app): replace AddressInfoWindow with in-app overlay
The address detail panel is now rendered as a modal overlay inside MainWindow instead of a separate top-level Window, avoiding the create/destroy cost of a dialog and working better under WSLg. Backdrop tap and Esc both close the overlay.
This commit is contained in:
@@ -249,6 +249,17 @@ public partial class MainWindowViewModel : ViewModelBase
|
|||||||
[ObservableProperty]
|
[ObservableProperty]
|
||||||
private AddressRow? selectedAddressRow;
|
private AddressRow? selectedAddressRow;
|
||||||
|
|
||||||
|
/// <summary>Dettaglio indirizzo mostrato nell'overlay in-app; null = nascosto.</summary>
|
||||||
|
[ObservableProperty]
|
||||||
|
private AddressInfo? addressInfo;
|
||||||
|
|
||||||
|
/// <summary>Apre l'overlay con i dati dell'indirizzo passato.</summary>
|
||||||
|
public void ShowAddressInfo(AddressRow row) =>
|
||||||
|
AddressInfo = new AddressInfo(Loc, row.Indirizzo, row.DerivPath, row.PubKey, row.PrivKey);
|
||||||
|
|
||||||
|
[RelayCommand]
|
||||||
|
private void CloseAddressInfo() => AddressInfo = null;
|
||||||
|
|
||||||
// ---- rubrica contatti ----
|
// ---- rubrica contatti ----
|
||||||
|
|
||||||
public ObservableCollection<ContactEntry> Contacts { get; } = [];
|
public ObservableCollection<ContactEntry> Contacts { get; } = [];
|
||||||
|
|||||||
@@ -1,49 +0,0 @@
|
|||||||
<Window xmlns="https://github.com/avaloniaui"
|
|
||||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
|
||||||
xmlns:vm="using:PalladiumWallet.App.ViewModels"
|
|
||||||
x:Class="PalladiumWallet.App.Views.AddressInfoWindow"
|
|
||||||
x:DataType="vm:AddressInfo"
|
|
||||||
Title="{Binding Loc[addr.info.title]}"
|
|
||||||
Width="560" SizeToContent="Height"
|
|
||||||
CanResize="False"
|
|
||||||
WindowStartupLocation="CenterOwner">
|
|
||||||
|
|
||||||
<StackPanel Margin="24" Spacing="16">
|
|
||||||
|
|
||||||
<!-- Indirizzo -->
|
|
||||||
<StackPanel Spacing="4">
|
|
||||||
<TextBlock Text="{Binding Loc[addr.address]}" FontSize="11" Foreground="Gray"/>
|
|
||||||
<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="Gray"/>
|
|
||||||
<SelectableTextBlock Text="{Binding DerivPath}"
|
|
||||||
FontFamily="monospace" FontSize="13"/>
|
|
||||||
</StackPanel>
|
|
||||||
|
|
||||||
<!-- Chiave pubblica -->
|
|
||||||
<StackPanel Spacing="4">
|
|
||||||
<TextBlock Text="{Binding Loc[addr.pubkey]}" FontSize="11" Foreground="Gray"/>
|
|
||||||
<SelectableTextBlock Text="{Binding PubKey}"
|
|
||||||
FontFamily="monospace" FontSize="12"
|
|
||||||
TextWrapping="Wrap"/>
|
|
||||||
</StackPanel>
|
|
||||||
|
|
||||||
<!-- Chiave privata (solo se disponibile) -->
|
|
||||||
<StackPanel Spacing="4" IsVisible="{Binding HasPrivKey}">
|
|
||||||
<TextBlock Text="{Binding Loc[addr.privkey]}" FontSize="11" Foreground="OrangeRed"/>
|
|
||||||
<SelectableTextBlock Text="{Binding PrivKey}"
|
|
||||||
FontFamily="monospace" FontSize="12"
|
|
||||||
Foreground="OrangeRed"
|
|
||||||
TextWrapping="Wrap"/>
|
|
||||||
</StackPanel>
|
|
||||||
|
|
||||||
<Button Content="{Binding Loc[addr.close]}"
|
|
||||||
HorizontalAlignment="Right"
|
|
||||||
Click="OnCloseClick"/>
|
|
||||||
</StackPanel>
|
|
||||||
</Window>
|
|
||||||
@@ -1,20 +0,0 @@
|
|||||||
using Avalonia.Controls;
|
|
||||||
using Avalonia.Interactivity;
|
|
||||||
using PalladiumWallet.App.ViewModels;
|
|
||||||
|
|
||||||
namespace PalladiumWallet.App.Views;
|
|
||||||
|
|
||||||
public partial class AddressInfoWindow : Window
|
|
||||||
{
|
|
||||||
public AddressInfoWindow()
|
|
||||||
{
|
|
||||||
InitializeComponent();
|
|
||||||
}
|
|
||||||
|
|
||||||
public AddressInfoWindow(AddressInfo info) : this()
|
|
||||||
{
|
|
||||||
DataContext = info;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void OnCloseClick(object? sender, RoutedEventArgs e) => Close();
|
|
||||||
}
|
|
||||||
@@ -375,5 +375,60 @@
|
|||||||
Padding="10,6">
|
Padding="10,6">
|
||||||
<TextBlock Text="{Binding StatusMessage}" FontSize="12" TextWrapping="Wrap"/>
|
<TextBlock Text="{Binding StatusMessage}" FontSize="12" TextWrapping="Wrap"/>
|
||||||
</Border>
|
</Border>
|
||||||
|
|
||||||
|
<!-- ============ OVERLAY DETTAGLIO INDIRIZZO ============ -->
|
||||||
|
<!-- Overlay in-app invece di una Window separata: apertura/chiusura
|
||||||
|
istantanee (niente create/destroy di una top-level window). -->
|
||||||
|
<Border Grid.Row="0" Grid.RowSpan="3"
|
||||||
|
Background="#99000000"
|
||||||
|
Tapped="OnAddressOverlayBackdropTapped"
|
||||||
|
IsVisible="{Binding AddressInfo, Converter={x:Static ObjectConverters.IsNotNull}}">
|
||||||
|
<Border Background="{DynamicResource SystemControlBackgroundChromeMediumLowBrush}"
|
||||||
|
BorderBrush="Gray" BorderThickness="1" CornerRadius="8"
|
||||||
|
Width="560" Padding="0"
|
||||||
|
HorizontalAlignment="Center" VerticalAlignment="Center"
|
||||||
|
DataContext="{Binding AddressInfo}">
|
||||||
|
<StackPanel Margin="24" Spacing="16">
|
||||||
|
<TextBlock Text="{Binding Loc[addr.info.title]}"
|
||||||
|
FontSize="18" FontWeight="Bold"/>
|
||||||
|
|
||||||
|
<!-- Indirizzo -->
|
||||||
|
<StackPanel Spacing="4">
|
||||||
|
<TextBlock Text="{Binding Loc[addr.address]}" FontSize="11" Foreground="Gray"/>
|
||||||
|
<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="Gray"/>
|
||||||
|
<SelectableTextBlock Text="{Binding DerivPath}"
|
||||||
|
FontFamily="monospace" FontSize="13"/>
|
||||||
|
</StackPanel>
|
||||||
|
|
||||||
|
<!-- Chiave pubblica -->
|
||||||
|
<StackPanel Spacing="4">
|
||||||
|
<TextBlock Text="{Binding Loc[addr.pubkey]}" FontSize="11" Foreground="Gray"/>
|
||||||
|
<SelectableTextBlock Text="{Binding PubKey}"
|
||||||
|
FontFamily="monospace" FontSize="12"
|
||||||
|
TextWrapping="Wrap"/>
|
||||||
|
</StackPanel>
|
||||||
|
|
||||||
|
<!-- Chiave privata (solo se disponibile) -->
|
||||||
|
<StackPanel Spacing="4" IsVisible="{Binding HasPrivKey}">
|
||||||
|
<TextBlock Text="{Binding Loc[addr.privkey]}" FontSize="11" Foreground="OrangeRed"/>
|
||||||
|
<SelectableTextBlock Text="{Binding PrivKey}"
|
||||||
|
FontFamily="monospace" FontSize="12"
|
||||||
|
Foreground="OrangeRed"
|
||||||
|
TextWrapping="Wrap"/>
|
||||||
|
</StackPanel>
|
||||||
|
|
||||||
|
<Button Content="{Binding Loc[addr.close]}"
|
||||||
|
HorizontalAlignment="Right"
|
||||||
|
Command="{Binding $parent[Window].((vm:MainWindowViewModel)DataContext).CloseAddressInfoCommand}"/>
|
||||||
|
</StackPanel>
|
||||||
|
</Border>
|
||||||
|
</Border>
|
||||||
</Grid>
|
</Grid>
|
||||||
</Window>
|
</Window>
|
||||||
|
|||||||
@@ -37,15 +37,14 @@ public partial class MainWindow : Window
|
|||||||
vm.OpenFromPath(path);
|
vm.OpenFromPath(path);
|
||||||
}
|
}
|
||||||
|
|
||||||
private async void OnAddressListTapped(object? sender, TappedEventArgs e)
|
private void OnAddressListTapped(object? sender, TappedEventArgs e)
|
||||||
{
|
{
|
||||||
if (DataContext is not MainWindowViewModel vm || vm.SelectedAddressRow is not { } row)
|
if (DataContext is not MainWindowViewModel vm || vm.SelectedAddressRow is not { } row)
|
||||||
return;
|
return;
|
||||||
var info = new AddressInfo(vm.Loc, row.Indirizzo, row.DerivPath, row.PubKey, row.PrivKey);
|
vm.ShowAddressInfo(row);
|
||||||
await new AddressInfoWindow(info).ShowDialog(this);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private async void OnAddressListPointerPressed(object? sender, PointerPressedEventArgs e)
|
private void OnAddressListPointerPressed(object? sender, PointerPressedEventArgs e)
|
||||||
{
|
{
|
||||||
if (!e.GetCurrentPoint(null).Properties.IsRightButtonPressed) return;
|
if (!e.GetCurrentPoint(null).Properties.IsRightButtonPressed) return;
|
||||||
if (sender is not ListBox lb || DataContext is not MainWindowViewModel vm) return;
|
if (sender is not ListBox lb || DataContext is not MainWindowViewModel vm) return;
|
||||||
@@ -54,8 +53,26 @@ public partial class MainWindow : Window
|
|||||||
if (item is not { DataContext: AddressRow row }) return;
|
if (item is not { DataContext: AddressRow row }) return;
|
||||||
|
|
||||||
lb.SelectedItem = row;
|
lb.SelectedItem = row;
|
||||||
|
vm.ShowAddressInfo(row);
|
||||||
|
}
|
||||||
|
|
||||||
var info = new AddressInfo(vm.Loc, row.Indirizzo, row.DerivPath, row.PubKey, row.PrivKey);
|
// Chiusura dell'overlay dettaglio indirizzo: click sullo sfondo scuro
|
||||||
await new AddressInfoWindow(info).ShowDialog(this);
|
// (solo sullo sfondo, non sulla scheda) o tasto Esc.
|
||||||
|
private void OnAddressOverlayBackdropTapped(object? sender, TappedEventArgs e)
|
||||||
|
{
|
||||||
|
if (!ReferenceEquals(e.Source, sender)) return;
|
||||||
|
if (DataContext is MainWindowViewModel vm)
|
||||||
|
vm.AddressInfo = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void OnKeyDown(KeyEventArgs e)
|
||||||
|
{
|
||||||
|
if (e.Key == Key.Escape && DataContext is MainWindowViewModel { AddressInfo: not null } vm)
|
||||||
|
{
|
||||||
|
vm.AddressInfo = null;
|
||||||
|
e.Handled = true;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
base.OnKeyDown(e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user