feat(app): settings menu with language and display unit
Add global AppConfig (config.json, blueprint §8) persisting language and amount unit. CoinAmount gains unit-aware formatting and parsing (PLM, mPLM, µPLM, sat), applied everywhere amounts are shown or entered, including the send form. New Loc i18n layer (it/en) with live-updating XAML bindings covering menu, wizard, wallet panel and status messages. The Impostazioni menu opens a dropdown with separate Lingua and Unità entries (radio-checked submenus, applied and saved on click), ready to host future settings.
This commit is contained in:
@@ -0,0 +1,42 @@
|
||||
using System.Text.Json;
|
||||
|
||||
namespace PalladiumWallet.Core.Storage;
|
||||
|
||||
/// <summary>
|
||||
/// Configurazione globale dell'applicazione (blueprint §8), separata dai file
|
||||
/// wallet: lingua, unità di visualizzazione, ecc. Persistita in config.json
|
||||
/// nella radice dei dati (vale per tutte le reti).
|
||||
/// </summary>
|
||||
public sealed class AppConfig
|
||||
{
|
||||
/// <summary>Codice lingua UI ("it", "en").</summary>
|
||||
public string Language { get; set; } = "it";
|
||||
|
||||
/// <summary>Unità di visualizzazione degli importi (vedi <see cref="Wallet.CoinAmount.Units"/>).</summary>
|
||||
public string Unit { get; set; } = "PLM";
|
||||
|
||||
private static readonly JsonSerializerOptions JsonOptions = new() { WriteIndented = true };
|
||||
|
||||
public static AppConfig Load(string? path = null)
|
||||
{
|
||||
path ??= AppPaths.ConfigPath();
|
||||
if (!File.Exists(path))
|
||||
return new AppConfig();
|
||||
try
|
||||
{
|
||||
return JsonSerializer.Deserialize<AppConfig>(File.ReadAllText(path)) ?? new AppConfig();
|
||||
}
|
||||
catch (JsonException)
|
||||
{
|
||||
// Config corrotta: si riparte dai default senza bloccare l'avvio.
|
||||
return new AppConfig();
|
||||
}
|
||||
}
|
||||
|
||||
public void Save(string? path = null)
|
||||
{
|
||||
path ??= AppPaths.ConfigPath();
|
||||
Directory.CreateDirectory(Path.GetDirectoryName(path)!);
|
||||
File.WriteAllText(path, JsonSerializer.Serialize(this, JsonOptions));
|
||||
}
|
||||
}
|
||||
@@ -10,10 +10,51 @@ public static class CoinAmount
|
||||
{
|
||||
public const long SatsPerCoin = 100_000_000;
|
||||
|
||||
/// <summary>Unità di visualizzazione selezionabili (config §8).</summary>
|
||||
public static readonly string[] Units = ["PLM", "mPLM", "µPLM", "sat"];
|
||||
|
||||
/// <summary>(satoshi per unità, decimali mostrati) di ciascuna unità.</summary>
|
||||
private static (long Factor, int Decimals) Of(string unit) => unit switch
|
||||
{
|
||||
"mPLM" => (100_000, 5),
|
||||
"µPLM" => (100, 2),
|
||||
"sat" => (1, 0),
|
||||
_ => (SatsPerCoin, 8), // PLM
|
||||
};
|
||||
|
||||
public static string Format(long sats, string unit = "") =>
|
||||
(sats / (decimal)SatsPerCoin).ToString("0.00000000", CultureInfo.InvariantCulture)
|
||||
+ (unit.Length > 0 ? " " + unit : "");
|
||||
|
||||
/// <summary>Formatta nell'unità scelta (es. 150000 sat → "1.50000 mPLM").</summary>
|
||||
public static string FormatIn(long sats, string unit, bool withLabel = true)
|
||||
{
|
||||
var (factor, decimals) = Of(unit);
|
||||
var value = (sats / (decimal)factor).ToString(
|
||||
decimals == 0 ? "0" : "0." + new string('0', decimals), CultureInfo.InvariantCulture);
|
||||
return withLabel ? $"{value} {unit}" : value;
|
||||
}
|
||||
|
||||
/// <summary>Parsa un importo espresso nell'unità scelta in satoshi.</summary>
|
||||
public static bool TryParseIn(string text, string unit, out long sats)
|
||||
{
|
||||
sats = 0;
|
||||
var (factor, _) = Of(unit);
|
||||
text = text.Trim().Replace(',', '.');
|
||||
if (!decimal.TryParse(text, NumberStyles.Number, CultureInfo.InvariantCulture, out var value)
|
||||
|| value < 0)
|
||||
return false;
|
||||
try
|
||||
{
|
||||
sats = (long)(value * factor);
|
||||
}
|
||||
catch (OverflowException)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>Parsa un importo in coin (punto o virgola decimale) in satoshi.</summary>
|
||||
public static bool TryParseCoins(string text, out long sats)
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user