feat(app): QR code for receive address

Adds QRCoder 1.8.0 and generates a PNG QR code in-memory each time
the receive address changes (OnReceiveAddressChanged). The bitmap is
displayed in the Receive tab inside a white-background border with
pixel-perfect scaling (BitmapInterpolationMode=None). Previous bitmap
is disposed to avoid memory leaks.
This commit is contained in:
2026-06-12 10:21:16 +02:00
parent 7f2759b2fc
commit 58b86ad1af
3 changed files with 36 additions and 0 deletions
+1
View File
@@ -22,6 +22,7 @@
<PrivateAssets Condition="'$(Configuration)' != 'Debug'">All</PrivateAssets>
</PackageReference>
<PackageReference Include="CommunityToolkit.Mvvm" Version="8.4.1" />
<PackageReference Include="QRCoder" Version="1.8.0" />
</ItemGroup>
<ItemGroup>
+29
View File
@@ -4,6 +4,7 @@ using System.Collections.ObjectModel;
using System.IO;
using System.Linq;
using System.Threading.Tasks;
using Avalonia.Media.Imaging;
using Avalonia.Threading;
using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Input;
@@ -15,6 +16,7 @@ using PalladiumWallet.Core.Net;
using PalladiumWallet.Core.Spv;
using PalladiumWallet.Core.Storage;
using PalladiumWallet.Core.Wallet;
using QRCoder;
namespace PalladiumWallet.App.ViewModels;
@@ -240,6 +242,33 @@ public partial class MainWindowViewModel : ViewModelBase
[ObservableProperty]
private string receiveAddress = "";
/// <summary>QR code dell'indirizzo di ricezione corrente (PNG in-memory).</summary>
[ObservableProperty]
private Bitmap? receiveQr;
// Rigenera il QR ogni volta che l'indirizzo di ricezione cambia.
partial void OnReceiveAddressChanged(string value)
{
var previous = ReceiveQr;
ReceiveQr = string.IsNullOrEmpty(value) ? null : GenerateQr(value);
previous?.Dispose();
}
private static Bitmap? GenerateQr(string text)
{
try
{
using var generator = new QRCodeGenerator();
using var data = generator.CreateQrCode(text, QRCodeGenerator.ECCLevel.M);
var png = new PngByteQRCode(data).GetGraphic(8);
return new Bitmap(new MemoryStream(png));
}
catch
{
return null;
}
}
[ObservableProperty]
private string serverHost = "";
+6
View File
@@ -255,6 +255,12 @@
<TextBlock Text="{Binding Loc[receive.next]}"/>
<SelectableTextBlock Text="{Binding ReceiveAddress}"
FontFamily="monospace" FontSize="16"/>
<Border Background="White" Padding="12" CornerRadius="6"
HorizontalAlignment="Left"
IsVisible="{Binding ReceiveQr, Converter={x:Static ObjectConverters.IsNotNull}}">
<Image Source="{Binding ReceiveQr}" Width="220" Height="220"
RenderOptions.BitmapInterpolationMode="None"/>
</Border>
<TextBlock Text="{Binding Loc[receive.hint]}"
Foreground="Gray" FontSize="12" TextWrapping="Wrap"/>
</StackPanel>