fix: give every address a row of its own, so none wraps or is shortened (closes #380)
The wallet list was the reported case. An address there shared one row with the [info] and [x] controls, which took about a third of the width off it, so all 42 characters folded onto a second line. A folded address is not a cosmetic problem: it turns one string the user is meant to compare against a known value into two shorter ones, which is the shape an address-poisoning attack wants. The fix is the layout, not the CSS. renderAddressHtml() -- the single renderer behind every common view that shows an address -- now emits an identity strip (colour dot, wallet title, explorer link, with the ENS name below it) and then the address alone on a full-width row. The wallet list moves [info] and [x] up onto the "Address N" line, which was empty to its right. The transaction rows on Home, the address screen and the token screen carried a truncateMiddle()d counterparty squeezed in beside the amount; they now name it on the amount line where we know it, and carry the whole address on the row below. With the row to itself, an address fits at every nesting depth the popup uses, including the transaction detail wells, which are the narrowest containers it has. .am-address holds nowrap so it cannot fold again, and overflow-x so that if it ever does not fit -- wider glyphs, a zoom -- the user can still reach the last character rather than having it clipped away by #app's overflow-x-hidden with nothing to say it happened. No caller passes maxLen any more, so the 32-character floor that lived in those call sites moved into renderAddressHtml(). truncateMiddle() and its 10-character cap are unchanged: the guarantee has to outlive having no current callers. tests/e2e measures it in a real Chromium rather than asserting on markup: whether an address wrapped is a question about glyph advances and the width of the box it landed in, and nothing in the HTML answers it. Every rendered address is checked for being whole, occupying one line box, fitting its row and ending inside the popup's content box, with the document itself not scrolling sideways -- across Home with a two-address wallet, the address, token, receive, send and transaction detail screens, the confirmation screen and the dApp transaction prompt.
This commit is contained in:
@@ -9,7 +9,6 @@ const {
|
||||
addressTitle,
|
||||
escapeHtml,
|
||||
displaySymbol,
|
||||
truncateMiddle,
|
||||
renderAddressHtml,
|
||||
attachCopyHandlers,
|
||||
pushCurrentView,
|
||||
@@ -117,10 +116,13 @@ function renderHomeTxList(ctx) {
|
||||
const amountStr = tx.value
|
||||
? escapeHtml(tx.value + " " + sym)
|
||||
: escapeHtml(sym);
|
||||
// The counterparty used to be squeezed in beside the amount and
|
||||
// truncated to whatever was left over. It gets its own row now and
|
||||
// is shown whole; the title, when it is one of our own addresses,
|
||||
// names it on the line above rather than replacing it.
|
||||
const title = addressTitle(counterparty, state.wallets);
|
||||
const maxAddr = Math.max(32, 36 - Math.max(0, amountStr.length - 10));
|
||||
const displayAddr = title || truncateMiddle(counterparty, maxAddr);
|
||||
const addrStr = escapeHtml(displayAddr);
|
||||
const titleStr = title ? escapeHtml(title) : "";
|
||||
const addrStr = escapeHtml(counterparty);
|
||||
const dot = addressDotHtml(counterparty);
|
||||
const err = tx.isError ? " (failed)" : "";
|
||||
const opacity = tx.isError ? " opacity:0.5;" : "";
|
||||
@@ -128,7 +130,8 @@ function renderHomeTxList(ctx) {
|
||||
const iso = escapeHtml(isoDate(tx.timestamp));
|
||||
html += `<div class="home-tx-row py-2 border-b border-border-light text-xs cursor-pointer hover:bg-hover" data-tx="${i}" style="${opacity}">`;
|
||||
html += `<div class="flex justify-between"><span class="text-muted" title="${iso}">${ago}</span><span>${dirLabel}${err}</span></div>`;
|
||||
html += `<div class="flex justify-between"><span class="flex items-center">${dot}${addrStr}</span><span>${amountStr}</span></div>`;
|
||||
html += `<div class="flex justify-between"><span class="flex items-center">${dot}${titleStr}</span><span>${amountStr}</span></div>`;
|
||||
html += `<div class="am-address">${addrStr}</div>`;
|
||||
html += `</div>`;
|
||||
i++;
|
||||
}
|
||||
@@ -252,17 +255,22 @@ function walletListHtml() {
|
||||
: "";
|
||||
const dot = addressDotHtml(addr.address);
|
||||
const titleBold = isActive ? "font-bold" : "";
|
||||
html += `<div class="text-xs ${titleBold}">Address ${ai + 1}</div>`;
|
||||
// [info] and [x] ride on the "Address N" line, which was empty
|
||||
// to its right, so the address below gets the row to itself.
|
||||
// They used to sit beside the address and take about a third of
|
||||
// the width off it, which is what made a 42-character address
|
||||
// fold onto a second line here and nowhere else (#380).
|
||||
html += `<div class="flex text-xs items-center justify-between">`;
|
||||
html += `<span class="flex items-center ${titleBold}">${dot}Address ${ai + 1}</span>`;
|
||||
html += `<span class="flex-shrink-0 ml-1">${infoBtn}${removeBtn}</span>`;
|
||||
html += `</div>`;
|
||||
if (addr.ensName) {
|
||||
// An ENS reverse record is whatever the name owner set it
|
||||
// to; renderAddressHtml() escapes its own copy of this and
|
||||
// this list was the one that did not.
|
||||
html += `<div class="text-xs font-bold flex items-center">${dot}${escapeHtml(addr.ensName)}</div>`;
|
||||
html += `<div class="text-xs font-bold">${escapeHtml(addr.ensName)}</div>`;
|
||||
}
|
||||
html += `<div class="flex text-xs items-center justify-between">`;
|
||||
html += `<span class="flex items-center break-all">${addr.ensName ? "" : dot}${escapeHtml(addr.address)}</span>`;
|
||||
html += `<span class="flex-shrink-0 ml-1">${infoBtn}${removeBtn}</span>`;
|
||||
html += `</div>`;
|
||||
html += `<div class="am-address text-xs">${escapeHtml(addr.address)}</div>`;
|
||||
const addrTotal = formatAddressTotal(getAddressValue(addr));
|
||||
html += `<div class="text-xs text-muted text-right min-h-[1rem]">${addrTotal || " "}</div>`;
|
||||
html += balanceLinesForAddress(
|
||||
|
||||
Reference in New Issue
Block a user