2026-06-24 15:37:55 +02:00
|
|
|
using System;
|
2026-06-12 16:06:37 +02:00
|
|
|
using System.Linq;
|
|
|
|
|
using Avalonia;
|
|
|
|
|
using Avalonia.Controls;
|
|
|
|
|
using Avalonia.Input;
|
|
|
|
|
using Avalonia.Input.Platform;
|
|
|
|
|
using Avalonia.Interactivity;
|
|
|
|
|
using Avalonia.Platform.Storage;
|
|
|
|
|
using Avalonia.VisualTree;
|
|
|
|
|
using PalladiumWallet.App.ViewModels;
|
|
|
|
|
|
|
|
|
|
namespace PalladiumWallet.App.Views;
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
2026-06-16 14:40:06 +02:00
|
|
|
/// App root view, shared between desktop (hosted in <see cref="MainWindow"/>)
|
|
|
|
|
/// and mobile (single-view root). All overlays are in-app so no separate windows
|
|
|
|
|
/// are needed. Top-level APIs (file picker, clipboard) are reached via
|
|
|
|
|
/// <see cref="TopLevel.GetTopLevel"/> because a UserControl does not expose them.
|
2026-06-12 16:06:37 +02:00
|
|
|
/// </summary>
|
|
|
|
|
public partial class MainView : UserControl
|
|
|
|
|
{
|
|
|
|
|
public MainView()
|
|
|
|
|
{
|
|
|
|
|
InitializeComponent();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void OnHistoryRowDoubleTapped(object? sender, TappedEventArgs e)
|
|
|
|
|
{
|
|
|
|
|
if (sender is not ListBox lb || DataContext is not MainWindowViewModel vm) return;
|
|
|
|
|
if (lb.SelectedItem is not HistoryRow row) return;
|
|
|
|
|
|
2026-06-16 14:40:06 +02:00
|
|
|
// In-app overlay: appears immediately with a spinner; data arrives from
|
|
|
|
|
// the server in the background. No top-level window (slow to open/close).
|
2026-06-12 16:06:37 +02:00
|
|
|
_ = vm.ShowTransactionDetailsAsync(row.Txid);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void OnTxDetailsOverlayBackdropTapped(object? sender, TappedEventArgs e)
|
|
|
|
|
{
|
|
|
|
|
if (!ReferenceEquals(e.Source, sender)) return;
|
|
|
|
|
if (DataContext is MainWindowViewModel vm)
|
|
|
|
|
vm.CloseTransactionDetailsCommand.Execute(null);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void OnAddressListTapped(object? sender, TappedEventArgs e)
|
|
|
|
|
{
|
|
|
|
|
if (DataContext is not MainWindowViewModel vm || vm.SelectedAddressRow is not { } row)
|
|
|
|
|
return;
|
|
|
|
|
vm.ShowAddressInfo(row);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void OnAddressListPointerPressed(object? sender, PointerPressedEventArgs e)
|
|
|
|
|
{
|
|
|
|
|
if (!e.GetCurrentPoint(null).Properties.IsRightButtonPressed) return;
|
|
|
|
|
if (sender is not ListBox lb || DataContext is not MainWindowViewModel vm) return;
|
|
|
|
|
|
|
|
|
|
var item = (e.Source as Visual)?.FindAncestorOfType<ListBoxItem>();
|
|
|
|
|
if (item is not { DataContext: AddressRow row }) return;
|
|
|
|
|
|
|
|
|
|
lb.SelectedItem = row;
|
|
|
|
|
vm.ShowAddressInfo(row);
|
|
|
|
|
}
|
|
|
|
|
|
2026-06-16 14:40:06 +02:00
|
|
|
// Close the address-detail overlay: click on the dark backdrop
|
|
|
|
|
// (backdrop only, not the card itself) or press Esc.
|
2026-06-12 16:06:37 +02:00
|
|
|
private void OnAddressOverlayBackdropTapped(object? sender, TappedEventArgs e)
|
|
|
|
|
{
|
|
|
|
|
if (!ReferenceEquals(e.Source, sender)) return;
|
|
|
|
|
if (DataContext is MainWindowViewModel vm)
|
|
|
|
|
vm.AddressInfo = null;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void OnServerOverlayBackdropTapped(object? sender, TappedEventArgs e)
|
|
|
|
|
{
|
|
|
|
|
if (!ReferenceEquals(e.Source, sender)) return;
|
|
|
|
|
if (DataContext is MainWindowViewModel vm)
|
|
|
|
|
vm.IsServerSettingsOpen = false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private async void OnChooseDataFolderClick(object? sender, RoutedEventArgs e)
|
|
|
|
|
{
|
|
|
|
|
if (DataContext is not MainWindowViewModel vm) return;
|
|
|
|
|
if (TopLevel.GetTopLevel(this)?.StorageProvider is not { } storage) return;
|
|
|
|
|
|
|
|
|
|
var folders = await storage.OpenFolderPickerAsync(new FolderPickerOpenOptions
|
|
|
|
|
{
|
|
|
|
|
Title = "Cartella dati Palladium Wallet",
|
|
|
|
|
AllowMultiple = false,
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
if (folders.FirstOrDefault()?.TryGetLocalPath() is { } path)
|
|
|
|
|
vm.ApplyDataLocation(path);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private async void OnCopyReceiveAddressClick(object? sender, RoutedEventArgs e)
|
|
|
|
|
{
|
|
|
|
|
if (DataContext is not MainWindowViewModel vm || string.IsNullOrEmpty(vm.ReceiveAddress))
|
|
|
|
|
return;
|
|
|
|
|
if (TopLevel.GetTopLevel(this)?.Clipboard is { } clipboard)
|
|
|
|
|
{
|
|
|
|
|
await clipboard.SetTextAsync(vm.ReceiveAddress);
|
|
|
|
|
vm.NotifyAddressCopied();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void OnConnectionStatusTapped(object? sender, TappedEventArgs e)
|
|
|
|
|
{
|
|
|
|
|
if (DataContext is MainWindowViewModel vm)
|
|
|
|
|
vm.IsServerSettingsOpen = true;
|
|
|
|
|
}
|
|
|
|
|
|
2026-06-21 22:27:31 +02:00
|
|
|
private void OnWalletInfoOverlayBackdropTapped(object? sender, TappedEventArgs e)
|
|
|
|
|
{
|
|
|
|
|
if (!ReferenceEquals(e.Source, sender)) return;
|
|
|
|
|
if (DataContext is MainWindowViewModel vm)
|
|
|
|
|
vm.CloseWalletInfoCommand.Execute(null);
|
|
|
|
|
}
|
|
|
|
|
|
2026-06-12 16:06:37 +02:00
|
|
|
private void OnSettingsOverlayBackdropTapped(object? sender, TappedEventArgs e)
|
|
|
|
|
{
|
|
|
|
|
if (!ReferenceEquals(e.Source, sender)) return;
|
|
|
|
|
if (DataContext is MainWindowViewModel vm)
|
|
|
|
|
vm.IsSettingsOpen = false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void OnHelpOverlayBackdropTapped(object? sender, TappedEventArgs e)
|
|
|
|
|
{
|
|
|
|
|
if (!ReferenceEquals(e.Source, sender)) return;
|
|
|
|
|
if (DataContext is MainWindowViewModel vm)
|
|
|
|
|
vm.IsHelpOpen = false;
|
|
|
|
|
}
|
2026-06-24 15:37:55 +02:00
|
|
|
|
|
|
|
|
private async void OnOpenBugReportClick(object? sender, RoutedEventArgs e)
|
|
|
|
|
{
|
|
|
|
|
var launcher = TopLevel.GetTopLevel(this)?.Launcher;
|
|
|
|
|
if (launcher is not null)
|
|
|
|
|
await launcher.LaunchUriAsync(new Uri(
|
|
|
|
|
"https://santantonio.sytes.net/davide/PalladiumWallet/issues/new"));
|
|
|
|
|
}
|
2026-06-12 16:06:37 +02:00
|
|
|
|
2026-06-16 14:40:06 +02:00
|
|
|
// Esc (desktop) or Back (Android) closes the topmost open overlay.
|
2026-06-12 16:06:37 +02:00
|
|
|
protected override void OnKeyDown(KeyEventArgs e)
|
|
|
|
|
{
|
|
|
|
|
if ((e.Key == Key.Escape || e.Key == Key.Back) && DataContext is MainWindowViewModel vm)
|
|
|
|
|
{
|
|
|
|
|
if (vm.IsTxDetailsOpen) { vm.CloseTransactionDetailsCommand.Execute(null); e.Handled = true; return; }
|
2026-06-21 22:27:31 +02:00
|
|
|
if (vm.IsPrivKeyPromptOpen) { vm.CancelPrivKeyPromptCommand.Execute(null); e.Handled = true; return; }
|
|
|
|
|
if (vm.AddressInfo is not null) { vm.CloseAddressInfoCommand.Execute(null); e.Handled = true; return; }
|
2026-06-12 16:06:37 +02:00
|
|
|
if (vm.IsServerSettingsOpen) { vm.IsServerSettingsOpen = false; e.Handled = true; return; }
|
2026-06-21 22:27:31 +02:00
|
|
|
if (vm.IsWalletInfoOpen) { vm.CloseWalletInfoCommand.Execute(null); e.Handled = true; return; }
|
2026-06-12 16:06:37 +02:00
|
|
|
if (vm.IsSettingsOpen) { vm.IsSettingsOpen = false; e.Handled = true; return; }
|
|
|
|
|
if (vm.IsHelpOpen) { vm.IsHelpOpen = false; e.Handled = true; return; }
|
|
|
|
|
}
|
|
|
|
|
base.OnKeyDown(e);
|
|
|
|
|
}
|
|
|
|
|
}
|