ui: black market buy page with seller list, payment panel, per-merchant accepted coins and auto-convert; wallet row keys beside the data cells
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
12a63c562f
commit
9d24840561
7 files changed
+262
-73
No files matched your search
@@ -990,7 +990,9 @@ namespace Decentralized
|
||||
var w = d.Wallets[i];
|
||||
int idx = i;
|
||||
bool isCurrent = idx == d.Current;
|
||||
b.BeginPanel(740f, 32f, TextAnchor.MiddleLeft, 4f, 0f);
|
||||
// 一行三块:数据格(整行反色的是这一块)、操作键(和顶栏页签一样的黑色触控键,放在纸面上)、连接状态靠右
|
||||
b.BeginRow(4f, TextAnchor.MiddleLeft);
|
||||
b.BeginPanel(cols[0] + cols[1] + cols[2] + cols[3] + 8f, 32f, TextAnchor.MiddleLeft, 4f, 0f);
|
||||
_rows.Add(new PledgerSkin.RowDef
|
||||
{
|
||||
Root = b.Last.root,
|
||||
@@ -1003,8 +1005,9 @@ namespace Decentralized
|
||||
Cell(b, cols[1], w.Address, false, TextAnchor.MiddleLeft);
|
||||
Cell(b, cols[2], Fmt.Credits(w.Value(Session.Price)), false, TextAnchor.MiddleRight);
|
||||
Cell(b, cols[3], Fmt.Credits(w.Taint), false, TextAnchor.MiddleRight);
|
||||
// 操作键一组(垂直居中、固定高度),连接状态单独靠右
|
||||
b.BeginPanel(cols[4] - 140f, 32f, TextAnchor.MiddleLeft, 0f, 0f);
|
||||
b.End();
|
||||
b.End();
|
||||
b.BeginPanel(cols[4] - 150f, 32f, TextAnchor.MiddleLeft, 0f, 0f);
|
||||
_clear.Add(b.Last.image);
|
||||
b.BeginRow(4f, TextAnchor.MiddleLeft);
|
||||
RowKey(b, L.T("wallets.open"), () => WalletWindow.Open(w));
|
||||
@@ -1013,7 +1016,7 @@ namespace Decentralized
|
||||
if (idx > 0) RowKey(b, _destroyPick == w.Address ? L.T("wallets.destroy.sure") : L.T("wallets.destroy"), () => DestroyWallet(w));
|
||||
b.End();
|
||||
b.End();
|
||||
b.BeginPanel(100f, 32f, TextAnchor.MiddleRight, 0f, 0f);
|
||||
b.BeginPanel(84f, 32f, TextAnchor.MiddleRight, 0f, 0f);
|
||||
_clear.Add(b.Last.image);
|
||||
b.BeginRow(0f, TextAnchor.MiddleRight);
|
||||
if (idx != d.Current) RowKey(b, L.T("wallets.use"), () => { d.Current = idx; Session.Save(); Open(); });
|
||||
@@ -1021,7 +1024,6 @@ namespace Decentralized
|
||||
b.End();
|
||||
b.End();
|
||||
b.End();
|
||||
b.End();
|
||||
}
|
||||
if (_renamePick != null) RenameRow(b);
|
||||
}
|
||||
@@ -1033,7 +1035,7 @@ namespace Decentralized
|
||||
var go = b.Last.root;
|
||||
if (go == null) return;
|
||||
var le = go.GetComponent<LayoutElement>() ?? go.AddComponent<LayoutElement>();
|
||||
le.minHeight = 24f; le.preferredHeight = 24f; le.flexibleHeight = 0f;
|
||||
le.minHeight = 26f; le.preferredHeight = 26f; le.flexibleHeight = 0f;
|
||||
}
|
||||
|
||||
private static string _destroyPick, _renamePick, _renameText = "";
|
||||
@@ -1146,7 +1148,6 @@ namespace Decentralized
|
||||
private static PayMode _mode = PayMode.Escrow;
|
||||
private static string _deskAsset = Assets.PSC;
|
||||
private static bool _deskIn = true;
|
||||
private static string _payAsset = Assets.CRT;
|
||||
private static readonly System.Collections.Generic.Dictionary<string, Sprite> IconCache = new System.Collections.Generic.Dictionary<string, Sprite>();
|
||||
|
||||
/// <summary>货架上的商品图:游戏物品自己的贴图(本 mod 的显卡用本 mod 的贴图)。</summary>
|
||||
@@ -1178,60 +1179,46 @@ namespace Decentralized
|
||||
{
|
||||
var tab = t;
|
||||
string name = L.T("black.sub." + t.ToString().ToLowerInvariant());
|
||||
PledgerSkin.Pick(b, name, tab == _blackTab, () => { _blackTab = tab; _message = null; _edit = null; Open(); }, _picked);
|
||||
PledgerSkin.Pick(b, name, tab == _blackTab, () => { _blackTab = tab; _message = null; _edit = null; _pay = null; Open(); }, _picked);
|
||||
}
|
||||
b.End();
|
||||
if (d.Black.Closed(day)) { b.AddLabel(L.T("black.rugged", d.Black.ClosedUntil - day + 1), "black_rugged_note"); return; }
|
||||
if (_pay != null && _blackTab != BlackTab.Buy) { PayPanel(b); return; }
|
||||
if (_edit != null) { EditPage(b); return; }
|
||||
if (_blackTab == BlackTab.Orders) { OrdersPage(b, day); return; }
|
||||
if (_blackTab == BlackTab.Sell) { SellPage(b, day); return; }
|
||||
BuyPage(b, d, rep);
|
||||
}
|
||||
|
||||
/// <summary>买货:选一家卖家(第一个是平台现货,立即到货但贵,其余是商家,便宜但要等),选件数,下单。论坛情报在最下面。</summary>
|
||||
/// <summary>
|
||||
/// 买货:左栏是卖家列表(第一个是平台现货,立即到货但贵,其余是商家,便宜但要等),右栏是这家的货架。
|
||||
/// 点"购买"后右栏换成付款面板:选数量(和付款方式)、付款币种;商家不收手里的币时可以用 Web3 内置的自动换币(多付滑点)。论坛情报在最下面。
|
||||
/// </summary>
|
||||
private static void BuyPage(CustomUIBuilder b, SaveData d, int rep)
|
||||
{
|
||||
var w = d.Hot;
|
||||
var sellers = d.Black.Sellers;
|
||||
if (_merchant >= sellers.Count) _merchant = -1;
|
||||
bool platform = _merchant < 0;
|
||||
b.AddLabel(L.T("black.rep", rep, BlackMarket.MaxLevel(rep)) + " " + L.T("mixer.balance", _payAsset, Fmt.Num(w.Avail(_payAsset))) + (w.Taint > 0.5 ? " " + L.T("wallet.taint", Fmt.Credits(w.Taint)) : ""));
|
||||
b.BeginRow(4f);
|
||||
foreach (var a in new[] { Assets.PSC, Assets.CRT, Assets.CRA, Assets.Ponero })
|
||||
b.AddLabel(L.T("black.rep", rep, BlackMarket.MaxLevel(rep)) + (w.Taint > 0.5 ? " " + L.T("wallet.taint", Fmt.Credits(w.Taint)) : ""), "black_rep_dim");
|
||||
b.BeginRow(8f, TextAnchor.UpperLeft);
|
||||
b.BeginPanel(SellerW + 8f, -1f, TextAnchor.UpperLeft, 0f, 2f);
|
||||
_clear.Add(b.Last.image);
|
||||
var names = new System.Collections.Generic.List<string> { L.T("merchant.Platform") };
|
||||
for (int k = 0; k < sellers.Count; k++) names.Add(MerchantLabel(sellers[k], true));
|
||||
for (int i = 0; i < names.Count; i++)
|
||||
{
|
||||
var asset = a;
|
||||
PledgerSkin.Pick(b, asset, asset == _payAsset, () => { _payAsset = asset; Open(); }, _picked);
|
||||
}
|
||||
if (!platform)
|
||||
foreach (PayMode m in Enum.GetValues(typeof(PayMode)))
|
||||
{
|
||||
var mode = m;
|
||||
string n = L.T("black.mode." + m);
|
||||
PledgerSkin.Pick(b, n, mode == _mode, () => { _mode = mode; Open(); }, _picked);
|
||||
}
|
||||
b.End();
|
||||
b.BeginRow(4f);
|
||||
foreach (var m in Qtys)
|
||||
{
|
||||
int q = m;
|
||||
PledgerSkin.Pick(b, "×" + q, q == _qty, () => { _qty = q; Open(); }, _picked);
|
||||
int idx = i - 1;
|
||||
TableRow(b, SellerW, new[] { SellerW - 8f }, new[] { TextAnchor.MiddleLeft }, new[] { names[i] }, idx == _merchant, () => { _merchant = idx; _pay = null; _message = null; Open(); });
|
||||
}
|
||||
b.End();
|
||||
var all = new System.Collections.Generic.List<System.Collections.Generic.KeyValuePair<int, string>> { new System.Collections.Generic.KeyValuePair<int, string>(-1, L.T("merchant.Platform") + " " + d.Address("platform")) };
|
||||
for (int k = 0; k < sellers.Count; k++) all.Add(new System.Collections.Generic.KeyValuePair<int, string>(k, MerchantLabel(sellers[k])));
|
||||
for (int i = 0; i < all.Count; i += 3)
|
||||
{
|
||||
b.BeginRow(4f);
|
||||
for (int k = i; k < Math.Min(all.Count, i + 3); k++)
|
||||
{
|
||||
int idx = all[k].Key; string n = all[k].Value;
|
||||
PledgerSkin.Pick(b, n, idx == _merchant, () => { _merchant = idx; Open(); }, _picked);
|
||||
}
|
||||
b.End();
|
||||
}
|
||||
b.AddSeparator();
|
||||
if (platform) PlatformShelf(b, d);
|
||||
b.BeginPanel(ShelfW, -1f, TextAnchor.UpperLeft, 0f, 4f);
|
||||
_clear.Add(b.Last.image);
|
||||
if (_pay != null) PayPanel(b);
|
||||
else if (platform) PlatformShelf(b, d);
|
||||
else MerchantShelf(b, d);
|
||||
b.End();
|
||||
b.End();
|
||||
b.AddSeparator();
|
||||
b.AddHeader(L.T("black.forum.h"));
|
||||
if (d.Black.Forum.Count == 0) b.AddLabel(L.T("black.forum.quiet"), "forum_quiet_dim");
|
||||
@@ -1239,18 +1226,153 @@ namespace Decentralized
|
||||
b.AddLabel(f.StartsWith("phish:") ? L.T("black.forum.phish", f.Substring(6)) : f.StartsWith("scam:") ? L.T("black.forum.scam", BlackDelivery.DisplayName(f.Substring(5))) : f.StartsWith("busted:") ? L.T("black.forum.busted", f.Substring(7)) : L.T("black.forum." + f), "forum_dim");
|
||||
}
|
||||
|
||||
private const float SellerW = 176f, ShelfW = 560f;
|
||||
|
||||
private static void PlatformShelf(CustomUIBuilder b, SaveData d)
|
||||
{
|
||||
b.AddLabel(L.T("black.platform.line", d.Address("platform")), "platform_line_dim");
|
||||
b.AddLabel(L.T("black.platform.line"), "platform_line_dim");
|
||||
if (d.Black.Offers.Count == 0) { b.AddLabel(L.T("black.empty"), "platform_empty_dim"); return; }
|
||||
Shelf(b, d.Black.Offers.Cast<BmGood>().ToList(), (c, g) =>
|
||||
{
|
||||
var offer = (BmOffer)g;
|
||||
int count = Math.Min(_qty, offer.Qty);
|
||||
GoodHead(c, g, L.T("black.stock", offer.Qty));
|
||||
c.AddLabel(L.T("black.price", offer.Price * count) + (count > 1 ? " ×" + count : ""));
|
||||
c.AddLabel(L.T("black.price", offer.Price));
|
||||
c.AddFlexibleSpace();
|
||||
c.AddButton(L.T("black.buy"), () => { string asset = _payAsset; BeginPay(d.Address("platform"), ItemName(offer.Item) + (count > 1 ? " ×" + count : ""), asset, offer.Price * count, pw => BuyOffer(offer, count, asset, pw)); });
|
||||
c.AddButton(L.T("black.buy"), () => OpenPay(new PayDraft
|
||||
{
|
||||
Title = ItemName(offer.Item), Address = d.Address("platform"), Accepted = Merchants.PlatformAccepts, MaxQty = offer.Qty,
|
||||
Credits = (q, m) => offer.Price * q,
|
||||
Execute = (asset, q, m, pw) => BuyOffer(offer, q, asset, pw),
|
||||
}));
|
||||
}, 3);
|
||||
}
|
||||
|
||||
// ——— 付款面板 ———
|
||||
|
||||
/// <summary>一次付款的草稿:买什么、收款地址、商家收哪些币、可选数量与付款方式、合计,以及付款成功后做的事。</summary>
|
||||
private sealed class PayDraft
|
||||
{
|
||||
public string Title, Address, Asset, SwapFrom;
|
||||
public string[] Accepted;
|
||||
public int MaxQty = 1, Qty = 1;
|
||||
public bool Modes;
|
||||
public PayMode Mode = PayMode.Escrow;
|
||||
public Func<int, PayMode, double> Credits;
|
||||
public Action<string, int, PayMode, Wallet> Execute;
|
||||
}
|
||||
|
||||
private static PayDraft _pay;
|
||||
|
||||
private static void OpenPay(PayDraft p)
|
||||
{
|
||||
var w = Session.Data.Hot;
|
||||
p.Asset = p.Accepted.FirstOrDefault(a => w.Avail(a) * Session.Price(a) >= p.Credits(1, p.Mode)) ?? p.Accepted[0];
|
||||
p.SwapFrom = null;
|
||||
_pay = p;
|
||||
_message = null;
|
||||
Open();
|
||||
}
|
||||
|
||||
private static string Summary(PayDraft p) => p.Title + (p.Qty > 1 ? " ×" + p.Qty : "");
|
||||
|
||||
/// <summary>付款面板:数量、付款方式、合计、付款币种(商家收的币)、生成账单;下面是自动换币。</summary>
|
||||
private static void PayPanel(CustomUIBuilder b)
|
||||
{
|
||||
var d = Session.Data;
|
||||
var w = d.Hot;
|
||||
var p = _pay;
|
||||
if (p.Qty > p.MaxQty) p.Qty = p.MaxQty;
|
||||
b.AddHeader(L.T("bpay.h"));
|
||||
b.AddLabel(p.Title, "bpay_title");
|
||||
if (p.MaxQty > 1)
|
||||
{
|
||||
b.BeginRow(4f);
|
||||
b.AddLabel(L.T("bpay.qty"));
|
||||
foreach (var q in Qtys)
|
||||
{
|
||||
if (q > p.MaxQty && q != Qtys[0]) continue;
|
||||
int qq = q;
|
||||
PledgerSkin.Pick(b, "×" + qq, qq == p.Qty, () => { p.Qty = qq; Open(); }, _picked);
|
||||
}
|
||||
b.End();
|
||||
}
|
||||
if (p.Modes)
|
||||
{
|
||||
b.BeginRow(4f);
|
||||
foreach (PayMode m in Enum.GetValues(typeof(PayMode)))
|
||||
{
|
||||
var mode = m;
|
||||
PledgerSkin.Pick(b, L.T("black.mode." + m), mode == p.Mode, () => { p.Mode = mode; Open(); }, _picked);
|
||||
}
|
||||
b.End();
|
||||
}
|
||||
double credits = p.Credits(p.Qty, p.Mode);
|
||||
b.AddLabel(L.T("bpay.total", Fmt.Credits(credits)), "bpay_total");
|
||||
b.AddSeparator();
|
||||
b.AddLabel(L.T("bpay.coin"), "bpay_coin_dim");
|
||||
b.BeginRow(4f);
|
||||
foreach (var a in p.Accepted)
|
||||
{
|
||||
string asset = a;
|
||||
PledgerSkin.Pick(b, asset, asset == p.Asset, () => { p.Asset = asset; Open(); }, _picked);
|
||||
}
|
||||
b.End();
|
||||
double need = WalletWindow.RoundUp(credits / Session.Price(p.Asset));
|
||||
b.AddLabel(L.T("bpay.need", WalletWindow.Amt(need), p.Asset, Fmt.Num(w.Avail(p.Asset))), "bpay_need_dim");
|
||||
b.AddButton(L.T("bpay.invoice"), () =>
|
||||
{
|
||||
string asset = p.Asset; int q = p.Qty; var mode = p.Mode;
|
||||
string summary = Summary(p);
|
||||
_pay = null;
|
||||
BeginPay(p.Address, summary, asset, credits, pw => p.Execute(asset, q, mode, pw));
|
||||
});
|
||||
b.AddSeparator();
|
||||
// 自动换币:从钱包里别的币里换出商家收的币,多付滑点;是合约调用,签名后一步完成
|
||||
b.AddLabel(L.T("bpay.swap.h", p.Asset), "bpay_swap_dim");
|
||||
double slipped = credits * (1 + Tuning.BmAutoSwapSlip);
|
||||
var sources = w.Balances.Keys.Where(a => !p.Accepted.Contains(a) && a != Assets.Ponero && Session.Price(a) > 0 && w.Avail(a) * Session.Price(a) >= slipped).ToList();
|
||||
if (sources.Count == 0) b.AddLabel(L.T("bpay.swap.none"), "bpay_swap_none_dim");
|
||||
else
|
||||
{
|
||||
if (p.SwapFrom == null || !sources.Contains(p.SwapFrom)) p.SwapFrom = sources[0];
|
||||
b.BeginRow(4f);
|
||||
foreach (var s in sources)
|
||||
{
|
||||
string src = s;
|
||||
PledgerSkin.Pick(b, src, src == p.SwapFrom, () => { p.SwapFrom = src; Open(); }, _picked);
|
||||
}
|
||||
b.End();
|
||||
double needSrc = WalletWindow.RoundUp(slipped / Session.Price(p.SwapFrom));
|
||||
b.AddLabel(L.T("bpay.swap.need", WalletWindow.Amt(needSrc), p.SwapFrom, (Tuning.BmAutoSwapSlip * 100).ToString("0", CultureInfo.InvariantCulture)), "bpay_swap_need_dim");
|
||||
b.AddButton(L.T("bpay.swap.btn"), () => SwapAndPay(p, credits, needSrc));
|
||||
}
|
||||
b.AddSpace(4f);
|
||||
b.AddButton(L.T("bpay.back"), () => { _pay = null; _message = null; Open(); });
|
||||
}
|
||||
|
||||
/// <summary>自动换币并付款:一次合约调用,先把别的币按滑点换成商家收的币,再下单。</summary>
|
||||
private static void SwapAndPay(PayDraft p, double credits, double needSrc)
|
||||
{
|
||||
var d = Session.Data;
|
||||
string src = p.SwapFrom, asset = p.Asset; int q = p.Qty; var mode = p.Mode;
|
||||
_pay = null;
|
||||
_message = L.T("hw.wait");
|
||||
Open();
|
||||
WalletWindow.OpenForBill(new WalletWindow.Bill
|
||||
{
|
||||
Contract = true, Asset = src, Amount = needSrc, Spend = needSrc,
|
||||
Summary = L.T("bpay.swap.sum", Summary(p), src, WalletWindow.Amt(needSrc), asset),
|
||||
Execute = pw =>
|
||||
{
|
||||
if (pw.Avail(src) + 1e-9 < needSrc) { _message = L.T("msg.balance"); Open(); return; }
|
||||
double got = credits / Session.Price(asset) * 1.002;
|
||||
pw.Add(src, -needSrc);
|
||||
pw.Add(asset, got);
|
||||
pw.RecordBuy(asset, got, credits);
|
||||
CandleChart.Trade(src, credits); CandleChart.Trade(asset, credits);
|
||||
Log.Info($"自动换币:{needSrc:0.####} {src} → {got:0.####} {asset}({credits:0} 信用点等值)");
|
||||
p.Execute(asset, q, mode, pw);
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
@@ -1269,11 +1391,16 @@ namespace Decentralized
|
||||
PledgerSkin.Pick(b, "×" + n, Math.Abs(mult - _sellMult) < 1e-9, () => { _sellMult = mult; Open(); }, _picked);
|
||||
}
|
||||
b.End();
|
||||
b.AddLabel(L.T("mixer.balance", _payAsset, Fmt.Num(d.Hot.Avail(_payAsset))) + " " + L.T("black.sell.rating", d.Black.Rating) + " " + L.T("black.sell.slots", d.Black.ActiveListings, Tuning.BmMaxListings));
|
||||
b.AddLabel(L.T("black.sell.rating", d.Black.Rating) + " " + L.T("black.sell.slots", d.Black.ActiveListings, Tuning.BmMaxListings), "sell_status_dim");
|
||||
b.AddButton(L.T("black.sell.all"), () =>
|
||||
{
|
||||
string asset = _payAsset; double mult = _sellMult;
|
||||
BeginPay(d.Address("platform"), L.T("black.sell.all") + L.T("pay.listfee", mult.ToString("0.0", CultureInfo.InvariantCulture)), asset, BlackDelivery.Sellable().Sum(it => BlackMarket.ListFee(BlackMarket.ListPriceOf(BlackDelivery.RefValue(it), mult))), pw => ListAll(asset, mult, pw));
|
||||
double mult = _sellMult;
|
||||
double fee = BlackDelivery.Sellable().Sum(it => BlackMarket.ListFee(BlackMarket.ListPriceOf(BlackDelivery.RefValue(it), mult)));
|
||||
OpenPay(new PayDraft
|
||||
{
|
||||
Title = L.T("black.sell.all") + L.T("pay.listfee", mult.ToString("0.0", CultureInfo.InvariantCulture)), Address = d.Address("platform"), Accepted = Merchants.PlatformAccepts,
|
||||
Credits = (q, m) => fee, Execute = (asset, q, m, pw) => ListAll(asset, mult, pw),
|
||||
});
|
||||
});
|
||||
b.AddSeparator();
|
||||
var items = BlackDelivery.Sellable();
|
||||
@@ -1331,47 +1458,45 @@ namespace Decentralized
|
||||
Open();
|
||||
}
|
||||
|
||||
private static string MerchantLabel(BmSeller s) => L.T("merchant." + s.Type) + " " + s.Name;
|
||||
private static string MerchantLabel(BmSeller s, bool shortName = false) => L.T("merchant." + s.Type) + " " + (shortName ? ChainAddress.Short(s.Name) : s.Name);
|
||||
|
||||
private static int _merchant = -1;
|
||||
private static int _qty = 1;
|
||||
private static readonly int[] Qtys = { 1, 5, 10 };
|
||||
|
||||
/// <summary>商家货架:选一家商家,看它这周的货,选件数下单。</summary>
|
||||
/// <summary>商家货架:这家的成交数、好评和到货天数,下面是这周的货;点"购买"进付款面板。</summary>
|
||||
private static void MerchantShelf(CustomUIBuilder b, SaveData d)
|
||||
{
|
||||
var sellers = d.Black.Sellers;
|
||||
var seller = sellers[_merchant];
|
||||
b.AddLabel(L.T("black.seller", MerchantLabel(seller), seller.Trades, seller.Rating) + " " + L.T("black.days", seller.Days));
|
||||
var goods = d.Black.Catalog.Where(l => l.Seller == _merchant).Cast<BmGood>().ToList();
|
||||
int merchant = _merchant;
|
||||
b.AddLabel(L.T("black.seller", MerchantLabel(seller), seller.Trades, seller.Rating) + " " + L.T("black.days", seller.Days), "black_seller_dim");
|
||||
var goods = d.Black.Catalog.Where(l => l.Seller == merchant).Cast<BmGood>().ToList();
|
||||
if (goods.Count == 0) { b.AddLabel(L.T("black.empty"), "shelf_empty_dim"); return; }
|
||||
Shelf(b, goods, (c, g) =>
|
||||
{
|
||||
var listing = (BmListing)g;
|
||||
int count = Math.Min(_qty, listing.Qty);
|
||||
GoodHead(c, g, L.T("black.stock", listing.Qty));
|
||||
c.AddLabel(L.T("black.price", BlackMarket.Pay(BlackMarket.OrderTotal(listing.Price, count), _mode)) + (count > 1 ? " ×" + count : ""));
|
||||
c.AddLabel(L.T("black.price", BlackMarket.Pay(BlackMarket.OrderTotal(listing.Price, 1), PayMode.Escrow)));
|
||||
c.AddFlexibleSpace();
|
||||
bool ok = _mode == PayMode.Escrow || seller.Advance;
|
||||
c.AddButton(ok ? L.T("black.order") : L.T("black.noadvance"), () =>
|
||||
c.AddButton(L.T("black.buy"), () => OpenPay(new PayDraft
|
||||
{
|
||||
if (!ok) return;
|
||||
string asset = _payAsset; var mode = _mode;
|
||||
BeginPay(seller.Name, ItemName(listing.Item) + (count > 1 ? " ×" + count : ""), asset, BlackMarket.Pay(BlackMarket.OrderTotal(listing.Price, count), mode), pw => PlaceOrder(listing, count, asset, mode, pw));
|
||||
});
|
||||
});
|
||||
Title = ItemName(listing.Item), Address = seller.Name, Accepted = Merchants.Accepts(seller.Type), MaxQty = listing.Qty, Modes = seller.Advance,
|
||||
Credits = (q, m) => BlackMarket.Pay(BlackMarket.OrderTotal(listing.Price, q), m),
|
||||
Execute = (asset, q, m, pw) => PlaceOrder(listing, q, asset, m, pw),
|
||||
}));
|
||||
}, 3);
|
||||
}
|
||||
|
||||
private const int ShelfCols = 4;
|
||||
private const float CardW = 172f, CardH = 268f;
|
||||
|
||||
/// <summary>货架:一行 4 张商品卡。</summary>
|
||||
private static void Shelf(CustomUIBuilder b, System.Collections.Generic.List<BmGood> goods, Action<CustomUIBuilder, BmGood> card)
|
||||
private static void Shelf(CustomUIBuilder b, System.Collections.Generic.List<BmGood> goods, Action<CustomUIBuilder, BmGood> card, int cols = ShelfCols)
|
||||
{
|
||||
for (int i = 0; i < goods.Count; i += ShelfCols)
|
||||
for (int i = 0; i < goods.Count; i += cols)
|
||||
{
|
||||
b.BeginRow(6f);
|
||||
for (int k = i; k < Math.Min(goods.Count, i + ShelfCols); k++)
|
||||
for (int k = i; k < Math.Min(goods.Count, i + cols); k++)
|
||||
{
|
||||
var g = goods[k];
|
||||
b.BeginPanel(CardW, CardH, TextAnchor.UpperCenter, 6f, 3f);
|
||||
@@ -1497,9 +1622,12 @@ namespace Decentralized
|
||||
var d = Session.Data;
|
||||
int fee = e.Sale != null ? BlackMarket.RepriceFee(price) : BlackMarket.ListFee(price);
|
||||
_edit = null;
|
||||
string asset = _payAsset;
|
||||
BeginPay(d.Address("platform"), ItemName(e.Id) + L.T(e.Sale != null ? "pay.repricefee" : "pay.listfee", mult.ToString("0.00", CultureInfo.InvariantCulture)), asset, fee,
|
||||
pw => { if (e.Sale != null) RepriceSale(e.Sale, mult, asset, pw); else ListItem(e.Item, mult, asset, pw); });
|
||||
OpenPay(new PayDraft
|
||||
{
|
||||
Title = ItemName(e.Id) + L.T(e.Sale != null ? "pay.repricefee" : "pay.listfee", mult.ToString("0.00", CultureInfo.InvariantCulture)), Address = d.Address("platform"), Accepted = Merchants.PlatformAccepts,
|
||||
Credits = (q, m) => fee,
|
||||
Execute = (asset, q, m, pw) => { if (e.Sale != null) RepriceSale(e.Sale, mult, asset, pw); else ListItem(e.Item, mult, asset, pw); },
|
||||
});
|
||||
});
|
||||
b.AddButton(L.T("black.edit.cancel"), () => { _edit = null; _message = null; Open(); });
|
||||
b.End();
|
||||
|
||||
Reference in new issue
Block a user