Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
68 changes: 47 additions & 21 deletions OneGateApp/Pages/ReceivePage.xaml
Original file line number Diff line number Diff line change
Expand Up @@ -2,29 +2,55 @@
<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:og="http://schemas.neoorder.org/onegate/controls"
xmlns:toolkit="http://schemas.microsoft.com/dotnet/2022/maui/toolkit"
xmlns:zxing="clr-namespace:ZXing.Net.Maui.Controls;assembly=ZXing.Net.MAUI.Controls"
x:Class="NeoOrder.OneGate.Pages.ReceivePage"
Title="{x:Static og:Strings.Receive}"
SafeAreaEdges="All"
BindingContext="{Binding Source={RelativeSource Self}}"
Shell.TabBarIsVisible="False">
<Grid RowDefinitions="auto,*,auto" RowSpacing="30" Padding="20">
<Border x:Name="qrCodeCard" Padding="20" BackgroundColor="{AppThemeBinding Light=White, Dark=Black}" StrokeShape="RoundRectangle 10">
<Border.Shadow>
<Shadow Brush="Black" Offset="0,8" Radius="12" Opacity="0.25" />
</Border.Shadow>
<VerticalStackLayout Spacing="10">
<Label Text="{x:Static og:Strings.ReceiveQRCodeTitle}" HorizontalOptions="Center" />
<ContentView WidthRequest="250" HeightRequest="250">
<zxing:BarcodeGeneratorView Format="QrCode" Value="{Binding AddressUri}" />
</ContentView>
<Label Text="{Binding Wallet.Name}" FontAttributes="Bold" HorizontalOptions="Center" />
<Grid ColumnDefinitions="*,auto">
<Label StyleClass="Secondary" Text="{Binding DefaultAccount.Address}" LineBreakMode="MiddleTruncation" VerticalOptions="Center" />
<Button Grid.Column="1" StyleClass="Icon, IconSecondary" Text="&#xe664;" FontSize="20" Margin="-20" Padding="20" VerticalOptions="Center" Command="{x:Static og:Commands.Copy}" CommandParameter="{Binding DefaultAccount.Address}" />
</Grid>
</VerticalStackLayout>
</Border>
<Label Grid.Row="1" StyleClass="Secondary" Text="{x:Static og:Strings.ReceiveQRCodeText}" HorizontalTextAlignment="Center" />
<Button Grid.Row="2" Text="{x:Static og:Strings.SaveToPhotoLibrary}" Clicked="OnSaveToPhotoLibrary" />
</Grid>
</ContentPage>
<ScrollView>
<VerticalStackLayout Padding="20,20,20,32" Spacing="18">
<Border x:Name="qrCodeCard" Padding="18" BackgroundColor="{AppThemeBinding Light=White, Dark=Black}" StrokeShape="RoundRectangle 8">
<Border.Shadow>
<Shadow Brush="Black" Offset="0,8" Radius="12" Opacity="0.18" />
</Border.Shadow>
<VerticalStackLayout Spacing="12">
<Label Text="{x:Static og:Strings.ReceiveQRCodeTitle}" FontAttributes="Bold" HorizontalOptions="Center" />
<ContentView WidthRequest="228" HeightRequest="228" HorizontalOptions="Center">
<zxing:BarcodeGeneratorView Format="QrCode" Value="{Binding AddressUri}" />
</ContentView>
<Label Text="{Binding Wallet.Name}" FontAttributes="Bold" HorizontalOptions="Center" />
<Label StyleClass="Secondary" Text="{Binding RequestSummary}" FontSize="12" HorizontalTextAlignment="Center" LineBreakMode="WordWrap" IsVisible="{Binding HasRequestSummary}" />
<Grid ColumnDefinitions="*,auto" ColumnSpacing="8">
<Label StyleClass="Secondary" Text="{Binding DefaultAccount.Address}" LineBreakMode="MiddleTruncation" VerticalOptions="Center" />
<Button Grid.Column="1" StyleClass="Icon, IconSecondary" Text="&#xe664;" FontSize="20" Padding="10" VerticalOptions="Center" Command="{x:Static og:Commands.Copy}" CommandParameter="{Binding DefaultAccount.Address}" />
</Grid>
</VerticalStackLayout>
</Border>

<Border Padding="16" BackgroundColor="{toolkit:AppThemeResource TextBox}" StrokeShape="RoundRectangle 8">
<VerticalStackLayout Spacing="12">
<Label Text="{x:Static og:Strings.ReceiveRequestDetails}" FontAttributes="Bold" />

<VerticalStackLayout Spacing="5">
<Label StyleClass="Secondary" Text="{x:Static og:Strings.RequestMemo}" FontSize="12" />
<Border StrokeShape="RoundRectangle 5" BackgroundColor="{toolkit:AppThemeResource Panel}">
<Entry Text="{Binding Memo}" Placeholder="{x:Static og:Strings.RequestMemoPlaceholder}" ClearButtonVisibility="WhileEditing" og:Border.IsVisible="False" Margin="10,0" />
</Border>
</VerticalStackLayout>

<VerticalStackLayout Spacing="5">
<Label StyleClass="Secondary" Text="{x:Static og:Strings.RequestData}" FontSize="12" />
<Border StrokeShape="RoundRectangle 5" BackgroundColor="{toolkit:AppThemeResource Panel}">
<Entry Text="{Binding RequestData}" Placeholder="{x:Static og:Strings.RequestDataPlaceholder}" ClearButtonVisibility="WhileEditing" og:Border.IsVisible="False" Margin="10,0" />
</Border>
</VerticalStackLayout>
</VerticalStackLayout>
</Border>

<Button Text="{x:Static og:Strings.ShareQRCode}" ImageSource="{FontImageSource &#xe68b;, FontFamily=Icons, Size=18, Color={toolkit:AppThemeResource Accent}}" Clicked="OnShareQRCode" />
<Button StyleClass="Secondary" Text="{x:Static og:Strings.SaveToPhotoLibrary}" Clicked="OnSaveToPhotoLibrary" />
</VerticalStackLayout>
</ScrollView>
</ContentPage>
87 changes: 84 additions & 3 deletions OneGateApp/Pages/ReceivePage.xaml.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,17 +9,56 @@ namespace NeoOrder.OneGate.Pages;

public partial class ReceivePage : ContentPage, IQueryAttributable
{
string? memo;
string? requestData;

public Wallet Wallet { get; set { field = value; OnPropertyChanged(); } }
public WalletAccount DefaultAccount => Wallet.GetDefaultAccount()!;
public UInt160? Asset { get; set { field = value; OnPropertyChanged(); OnPropertyChanged(nameof(AddressUri)); } }
public string? Memo
{
get => memo;
set
{
if (memo == value) return;
memo = value;
OnPropertyChanged();
OnRequestDetailsChanged();
}
}
public string? RequestData
{
get => requestData;
set
{
if (requestData == value) return;
requestData = value;
OnPropertyChanged();
OnRequestDetailsChanged();
}
}
public bool HasRequestSummary => !string.IsNullOrWhiteSpace(Memo) || !string.IsNullOrWhiteSpace(RequestData);
public string RequestSummary
{
get
{
List<string> parts = [];
AddSummaryPart(parts, Strings.RequestMemo, Memo);
AddSummaryPart(parts, Strings.RequestData, RequestData);
return string.Join(Environment.NewLine, parts);
}
}
public string AddressUri
{
get
{
string uri = $"neo:{DefaultAccount.Address}";
string uri = $"neo:{Uri.EscapeDataString(DefaultAccount.Address)}";
List<string> query = [];
if (Asset is not null)
uri += $"?asset={Asset}";
return uri;
query.Add($"asset={Uri.EscapeDataString(Asset.ToString())}");
AddQueryParameter(query, "memo", Memo);
AddQueryParameter(query, "data", RequestData);
return query.Count == 0 ? uri : $"{uri}?{string.Join("&", query)}";
}
}

Expand All @@ -35,6 +74,48 @@ public void ApplyQueryAttributes(IDictionary<string, object> query)
Asset = (string)asset;
}

void OnRequestDetailsChanged()
{
OnPropertyChanged(nameof(AddressUri));
OnPropertyChanged(nameof(RequestSummary));
OnPropertyChanged(nameof(HasRequestSummary));
}

static void AddQueryParameter(List<string> query, string name, string? value)
{
value = value?.Trim();
if (string.IsNullOrEmpty(value)) return;
query.Add($"{name}={Uri.EscapeDataString(value)}");
}

static void AddSummaryPart(List<string> parts, string label, string? value)
{
value = value?.Trim();
if (string.IsNullOrEmpty(value)) return;
parts.Add($"{label}: {value}");
}

async void OnShareQRCode(object sender, EventArgs e)
{
string fileName = $"onegate-request-{DateTime.Now:yyyyMMdd-HHmmss}.png";
string path = Path.Combine(FileSystem.CacheDirectory, fileName);
IScreenshotResult? result = await qrCodeCard.CaptureAsync();
if (result is null)
{
await Toast.Show(Strings.ScreenshotFailed);
return;
}

await using Stream screenshot = await result.OpenReadAsync();
await using FileStream stream = File.Open(path, FileMode.Create, FileAccess.Write, FileShare.None);
await screenshot.CopyToAsync(stream);
await Share.RequestAsync(new ShareFileRequest
{
Title = Strings.ShareQRCode,
File = new ShareFile(path)
});
}

async void OnSaveToPhotoLibrary(object sender, EventArgs e)
{
string fileName = $"{DateTime.Now:yyyy-MM-dd HHmmss}.png";
Expand Down
54 changes: 54 additions & 0 deletions OneGateApp/Properties/Strings.Designer.cs

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

20 changes: 19 additions & 1 deletion OneGateApp/Properties/Strings.de.resx
Original file line number Diff line number Diff line change
Expand Up @@ -1037,4 +1037,22 @@ Es wird empfohlen, den NEP-2-Schlüssel und das Passwort getrennt aufzubewahren
<data name="Unavailable" xml:space="preserve">
<value>Nicht verfügbar</value>
</data>
</root>
<data name="ReceiveRequestDetails" xml:space="preserve">
<value>Anfragedetails</value>
</data>
<data name="RequestMemo" xml:space="preserve">
<value>Notiz</value>
</data>
<data name="RequestMemoPlaceholder" xml:space="preserve">
<value>Rechnung, Bestellung oder Hinweis</value>
</data>
<data name="RequestData" xml:space="preserve">
<value>Referenzdaten</value>
</data>
<data name="RequestDataPlaceholder" xml:space="preserve">
<value>Optionale Zahlungsreferenz</value>
</data>
<data name="ShareQRCode" xml:space="preserve">
<value>QR-Code teilen</value>
</data>
</root>
20 changes: 19 additions & 1 deletion OneGateApp/Properties/Strings.es.resx
Original file line number Diff line number Diff line change
Expand Up @@ -1037,4 +1037,22 @@ Se recomienda almacenar la clave NEP-2 y la contraseña por separado y realizar
<data name="Unavailable" xml:space="preserve">
<value>No disponible</value>
</data>
</root>
<data name="ReceiveRequestDetails" xml:space="preserve">
<value>Detalles de la solicitud</value>
</data>
<data name="RequestMemo" xml:space="preserve">
<value>Nota</value>
</data>
<data name="RequestMemoPlaceholder" xml:space="preserve">
<value>Factura, pedido o nota</value>
</data>
<data name="RequestData" xml:space="preserve">
<value>Datos de referencia</value>
</data>
<data name="RequestDataPlaceholder" xml:space="preserve">
<value>Referencia de pago opcional</value>
</data>
<data name="ShareQRCode" xml:space="preserve">
<value>Compartir código QR</value>
</data>
</root>
20 changes: 19 additions & 1 deletion OneGateApp/Properties/Strings.fr.resx
Original file line number Diff line number Diff line change
Expand Up @@ -1037,4 +1037,22 @@ Il est recommandé de conserver séparément la clé NEP-2 et le mot de passe, e
<data name="Unavailable" xml:space="preserve">
<value>Indisponible</value>
</data>
</root>
<data name="ReceiveRequestDetails" xml:space="preserve">
<value>Détails de la demande</value>
</data>
<data name="RequestMemo" xml:space="preserve">
<value>Mémo</value>
</data>
<data name="RequestMemoPlaceholder" xml:space="preserve">
<value>Facture, commande ou note</value>
</data>
<data name="RequestData" xml:space="preserve">
<value>Données de référence</value>
</data>
<data name="RequestDataPlaceholder" xml:space="preserve">
<value>Référence de paiement facultative</value>
</data>
<data name="ShareQRCode" xml:space="preserve">
<value>Partager le code QR</value>
</data>
</root>
20 changes: 19 additions & 1 deletion OneGateApp/Properties/Strings.id.resx
Original file line number Diff line number Diff line change
Expand Up @@ -1037,4 +1037,22 @@ Disarankan untuk menyimpan kunci NEP-2 dan kata sandinya secara terpisah serta m
<data name="Unavailable" xml:space="preserve">
<value>Tidak tersedia</value>
</data>
</root>
<data name="ReceiveRequestDetails" xml:space="preserve">
<value>Detail permintaan</value>
</data>
<data name="RequestMemo" xml:space="preserve">
<value>Memo</value>
</data>
<data name="RequestMemoPlaceholder" xml:space="preserve">
<value>Faktur, pesanan, atau catatan</value>
</data>
<data name="RequestData" xml:space="preserve">
<value>Data referensi</value>
</data>
<data name="RequestDataPlaceholder" xml:space="preserve">
<value>Referensi pembayaran opsional</value>
</data>
<data name="ShareQRCode" xml:space="preserve">
<value>Bagikan kode QR</value>
</data>
</root>
20 changes: 19 additions & 1 deletion OneGateApp/Properties/Strings.it.resx
Original file line number Diff line number Diff line change
Expand Up @@ -1037,4 +1037,22 @@ Si consiglia di conservare separatamente la chiave NEP-2 e la password e di eseg
<data name="Unavailable" xml:space="preserve">
<value>Non disponibile</value>
</data>
</root>
<data name="ReceiveRequestDetails" xml:space="preserve">
<value>Dettagli richiesta</value>
</data>
<data name="RequestMemo" xml:space="preserve">
<value>Memo</value>
</data>
<data name="RequestMemoPlaceholder" xml:space="preserve">
<value>Fattura, ordine o nota</value>
</data>
<data name="RequestData" xml:space="preserve">
<value>Dati di riferimento</value>
</data>
<data name="RequestDataPlaceholder" xml:space="preserve">
<value>Riferimento pagamento opzionale</value>
</data>
<data name="ShareQRCode" xml:space="preserve">
<value>Condividi codice QR</value>
</data>
</root>
Loading