Wallets: expected-days drain, copy/paste, three-column selectable balances, rename and destroy
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
783f73989d
commit
2b781acd82
10 files changed
+178
-22
No files matched your search
@@ -68,8 +68,9 @@ namespace Decentralized
|
||||
|
||||
public static string NameOf(Wallet w)
|
||||
{
|
||||
if (!string.IsNullOrWhiteSpace(w.Label)) return w.Label;
|
||||
int i = Session.Data.Wallets.IndexOf(w);
|
||||
return i == 0 ? L.T("hw.wallet.main") : L.T("hw.wallet.n", i + 1);
|
||||
return i == 0 ? L.T("hw.wallet.main") : L.T("hw.wallet.n", w.Name ?? (i + 1).ToString());
|
||||
}
|
||||
|
||||
private static Device Dev(Wallet w)
|
||||
@@ -80,6 +81,14 @@ namespace Decentralized
|
||||
|
||||
private static bool IsOpen(Device dev) => CustomUIManager.Instance != null && CustomUIManager.Instance.IsOpen(dev.Id);
|
||||
|
||||
/// <summary>钱包被销毁:关掉它的窗口,丢掉设备状态。</summary>
|
||||
public static void Close(Wallet w)
|
||||
{
|
||||
if (w == null || !Devices.TryGetValue(w.Address, out var dev)) return;
|
||||
if (IsOpen(dev)) CustomUIManager.Instance.CloseWindow(dev.Id);
|
||||
Devices.Remove(w.Address);
|
||||
}
|
||||
|
||||
/// <summary>读档 / 新游戏后清掉上一局的设备状态并关窗。</summary>
|
||||
public static void Reset()
|
||||
{
|
||||
@@ -115,6 +124,7 @@ namespace Decentralized
|
||||
WalletDriver.Ensure();
|
||||
var b = CustomUIManager.Window(dev.Id, "PLEDGER");
|
||||
if (b == null) return;
|
||||
_rows.Clear(); _clear.Clear();
|
||||
int idx = Session.Data.Wallets.IndexOf(dev.Wallet);
|
||||
b.SetSize(WinW, WinH).SetDraggable(true).SetCloseOnEscape(true).UseMachineryStyle();
|
||||
b.SetPosition(new Vector2(600f + 28f * idx, -24f * idx));
|
||||
@@ -181,6 +191,21 @@ namespace Decentralized
|
||||
if (img != null) img.color = Key;
|
||||
foreach (var t in btn.GetComponentsInChildren<TextMeshProUGUI>(true)) t.color = KeyText;
|
||||
}
|
||||
foreach (var img in _clear) if (img != null) img.color = new Color(0, 0, 0, 0);
|
||||
// 余额行:整行可点,选中的一行反色高亮
|
||||
foreach (var (root, img, asset) in _rows)
|
||||
{
|
||||
if (root == null || img == null) continue;
|
||||
bool on = asset == dev.Asset;
|
||||
img.sprite = MachineryStyle.White; img.type = Image.Type.Simple; img.raycastTarget = true;
|
||||
img.color = on ? Ink : new Color(0, 0, 0, 0.04f);
|
||||
foreach (var t in root.GetComponentsInChildren<TextMeshProUGUI>(true)) t.color = on ? KeyText : Ink;
|
||||
var btn = root.GetComponent<Button>() ?? root.AddComponent<Button>();
|
||||
btn.transition = Selectable.Transition.None;
|
||||
btn.onClick.RemoveAllListeners();
|
||||
string a = asset;
|
||||
btn.onClick.AddListener(() => { dev.Asset = a; dev.Note = null; Open(dev); });
|
||||
}
|
||||
// 签名要按住 ✓:在按键上挂一个按住计时
|
||||
if (ok != null && dev.Screen == Screen.Review && ok.GetComponent<HoldToSign>() == null) ok.AddComponent<HoldToSign>().Device = dev.Address;
|
||||
}
|
||||
@@ -203,6 +228,9 @@ namespace Decentralized
|
||||
}
|
||||
|
||||
private static readonly Dictionary<string, Sprite> Sliced = new Dictionary<string, Sprite>();
|
||||
private const float RowW = ScreenW - 28f;
|
||||
private static readonly List<(GameObject root, Image image, string asset)> _rows = new List<(GameObject, Image, string)>();
|
||||
private static readonly List<Image> _clear = new List<Image>();
|
||||
|
||||
public static string Amt(double v) => v.ToString(v >= 100 ? "0.##" : "0.####", CultureInfo.InvariantCulture);
|
||||
|
||||
@@ -214,16 +242,34 @@ namespace Decentralized
|
||||
private static void HomeScreen(CustomUIBuilder b, Device dev)
|
||||
{
|
||||
var w = dev.Wallet;
|
||||
b.AddHeader(NameOf(w));
|
||||
b.AddLabel("<size=22><b>" + NameOf(w) + "</b></size>");
|
||||
b.BeginRow(8f, TextAnchor.MiddleLeft);
|
||||
b.AddLabel(w.Address, "addr_dim");
|
||||
b.AddButton(L.T("hw.copy"), () => { Clipboard.Copy(w.Address); dev.Note = L.T("hw.copied"); Open(dev); });
|
||||
b.End();
|
||||
b.AddSeparator();
|
||||
bool any = false;
|
||||
foreach (var kv in w.Balances.OrderBy(k => k.Key))
|
||||
// 余额:每个币一行,左边币种、右边数量与估值,全部显示(含 0);点一行选中,发送时默认用它
|
||||
foreach (var a in SendAssets)
|
||||
{
|
||||
any = true;
|
||||
b.AddLabel(L.T("hw.balance", kv.Key, Amt(kv.Value), Fmt.Credits(kv.Value * Session.Price(kv.Key))));
|
||||
double q = w.Get(a);
|
||||
b.BeginPanel(RowW, 32f, TextAnchor.MiddleLeft, 6f, 0f);
|
||||
_rows.Add((b.Last.root, b.Last.image, a));
|
||||
b.BeginRow(0f, TextAnchor.MiddleLeft);
|
||||
b.BeginPanel(90f, 26f, TextAnchor.MiddleLeft, 0f, 0f);
|
||||
_clear.Add(b.Last.image);
|
||||
b.AddLabel(a);
|
||||
b.End();
|
||||
b.BeginPanel(130f, 26f, TextAnchor.MiddleRight, 0f, 0f);
|
||||
_clear.Add(b.Last.image);
|
||||
b.AddLabel(Amt(q) + (w.Frozen.TryGetValue(a, out var fz) && fz > 0 ? L.T("hw.balance.frozen", Amt(fz)) : ""));
|
||||
b.End();
|
||||
b.BeginPanel(RowW - 12f - 90f - 130f, 26f, TextAnchor.MiddleRight, 0f, 0f);
|
||||
_clear.Add(b.Last.image);
|
||||
b.AddLabel(L.T("hw.balance.value", Fmt.Credits(q * Session.Price(a))));
|
||||
b.End();
|
||||
b.End();
|
||||
b.End();
|
||||
}
|
||||
if (!any) b.AddLabel(L.T("wallet.empty"));
|
||||
b.AddSeparator();
|
||||
b.AddLabel(L.T("hw.total", Fmt.Credits(w.Value(Session.Price))));
|
||||
if (w.Taint > 0.5) b.AddLabel(L.T("wallet.taint", Fmt.Credits(w.Taint)));
|
||||
@@ -240,7 +286,13 @@ namespace Decentralized
|
||||
var w = dev.Wallet;
|
||||
b.AddHeader(L.T("hw.send"));
|
||||
b.AddLabel(L.T("hw.to"));
|
||||
b.BeginRow(6f, TextAnchor.MiddleLeft);
|
||||
b.BeginPanel(RowW - 70f, -1f, TextAnchor.MiddleLeft, 0f, 0f);
|
||||
_clear.Add(b.Last.image);
|
||||
b.AddInput("0x", dev.To, s => dev.To = s, "to", s => dev.To = s);
|
||||
b.End();
|
||||
b.AddButton(L.T("hw.paste"), () => { dev.To = Clipboard.Paste(); dev.Note = null; Open(dev); });
|
||||
b.End();
|
||||
b.BeginRow();
|
||||
foreach (var a in SendAssets)
|
||||
{
|
||||
@@ -452,10 +504,10 @@ namespace Decentralized
|
||||
}
|
||||
|
||||
/// <summary>别的交易让这个钱包的余额变了:开着的话刷新主页。</summary>
|
||||
public static void RefreshDevice(Wallet w)
|
||||
public static void RefreshDevice(Wallet w, bool any = false)
|
||||
{
|
||||
if (w == null || !Devices.TryGetValue(w.Address, out var dev) || !IsOpen(dev)) return;
|
||||
if (dev.Screen == Screen.Home || dev.Screen == Screen.Send) Open(dev);
|
||||
if (any || dev.Screen == Screen.Home || dev.Screen == Screen.Send) Open(dev);
|
||||
}
|
||||
|
||||
/// <summary>每帧推进出块动画:只改状态文字和进度条,不重建窗口。</summary>
|
||||
|
||||
Reference in new issue
Block a user