aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAdam Soltys <[email protected]>2026-11-15 14:29:52 -0700
committerAdam Soltys <[email protected]>2026-11-15 14:29:52 -0700
commit513fd7db08fb3c7e89fe651ac70913264a4bff22 (patch)
treea1b5e84f0bb90dc2e5d816259eff14b7650c5e97
parent392e73b9d163f39555895e9652d3a80f41cce6f3 (diff)
downloadcoinosv3-513fd7db08fb3c7e89fe651ac70913264a4bff22.tar.gz
coinosv3-513fd7db08fb3c7e89fe651ac70913264a4bff22.zip
No footer once a wallet is open, no empty history, no default name on a lone balance. "Actually those can go into settings too. And let's not show an empty history section just keep it hidden until we have history. I don't think we need the spending account name by default let's leave it blank unless the user supplies one" (Adam, 2026-11-15). The language and currency pickers now sit at the top of the Settings hub; the footer under every page is gone while a wallet is open (a visitor reading the public feed, with no wallet and so no Settings, still has them there; the wizard keeps its language picker). The wallet's history shows nothing at all until there's a first payment, instead of a 'No transactions yet' card. A single-balance account (a sign-up's Spending) shows no SPENDING over its amount unless its owner named it; the two-face carousel keeps Spending/Savings. footer-support (no footer with a wallet, pickers in Settings, About), signup-quick (no name on the lone face), chat-layout, onboard-backup, balance-settings-row, feed-window-dom and features-smoke pass
Co-Authored-By: Claude Opus 5.5 <[email protected]> Claude-Session: https://claude.ai/code/session_01VMan6SwkivduFDDkMmnXjZ
-rw-r--r--src/app.js14
-rw-r--r--src/style.css1
-rw-r--r--tools/chat-layout-test.js2
-rw-r--r--tools/footer-support-test.js9
-rw-r--r--tools/signup-quick-test.js2
5 files changed, 20 insertions, 8 deletions
diff --git a/src/app.js b/src/app.js
index 60b0ac9..0cf2447 100644
--- a/src/app.js
+++ b/src/app.js
@@ -380,6 +380,9 @@ function setupFooter() {
// here (credits, How it works, support, install, the theme, the commit) is
// on Settings → About (Adam, 2026-11-15).
function footer() {
+ // with a wallet open they're in Settings (Adam, 2026-11-15); a visitor
+ // reading the public feed still gets them here
+ if (activeAccount()) return h('div', { class: 'footer', style: 'display:none' });
return h('div', { class: 'footer small muted center' },
h('div', { class: 'row gap6', style: 'justify-content:center' }, languagePicker(), currencyPicker()));
}
@@ -3277,6 +3280,8 @@ function settingsTab() {
h('div', { class: 'row gap6', style: 'align-items:center;margin:2px 0 6px 4px' },
h('span', { style: 'display:flex;color:var(--muted)', html: '<svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="3"/><path d="M19.4 15a1.65 1.65 0 0 0 .33 1.82l.06.06a2 2 0 0 1 0 2.83 2 2 0 0 1-2.83 0l-.06-.06a1.65 1.65 0 0 0-1.82-.33 1.65 1.65 0 0 0-1 1.51V21a2 2 0 0 1-2 2 2 2 0 0 1-2-2v-.09A1.65 1.65 0 0 0 9 19.4a1.65 1.65 0 0 0-1.82.33l-.06.06a2 2 0 0 1-2.83 0 2 2 0 0 1 0-2.83l.06-.06a1.65 1.65 0 0 0 .33-1.82 1.65 1.65 0 0 0-1.51-1H3a2 2 0 0 1-2-2 2 2 0 0 1 2-2h.09A1.65 1.65 0 0 0 4.6 9a1.65 1.65 0 0 0-.33-1.82l-.06-.06a2 2 0 0 1 0-2.83 2 2 0 0 1 2.83 0l.06.06a1.65 1.65 0 0 0 1.82.33H9a1.65 1.65 0 0 0 1-1.51V3a2 2 0 0 1 2-2 2 2 0 0 1 2 2v.09a1.65 1.65 0 0 0 1 1.51 1.65 1.65 0 0 0 1.82-.33l.06-.06a2 2 0 0 1 2.83 0 2 2 0 0 1 0 2.83l-.06.06a1.65 1.65 0 0 0-.33 1.82V9a1.65 1.65 0 0 0 1.51 1H21a2 2 0 0 1 2 2 2 2 0 0 1-2 2h-.09a1.65 1.65 0 0 0-1.51 1z"/></svg>' }),
h('h3', { style: 'margin:0' }, t('tabSettings'))),
+ // display preferences, right at the top: the language and the currency
+ h('div', { class: 'row gap6 settings-prefs', style: 'margin:0 0 4px' }, languagePicker(), currencyPicker()),
grid([
tile('wallet', t('settingsWallet'), t('settingsWalletDesc')),
tile('payments', t('settingsPayments'), t('settingsPaymentsDesc')),
@@ -5304,7 +5309,9 @@ function balanceCard() {
})
: null,
h('div', { class: 'small faint', style: 'text-transform:uppercase;letter-spacing:.06em' },
- kindLocked ? viewLabel(acc0, view)
+ // a lone balance needs no name: blank unless its owner gave it
+ // one (Adam, 2026-11-15); the two-face carousel keeps its labels
+ kindLocked ? ((acc0.viewLabels && acc0.viewLabels[view]) || '')
: hasSpending ? (viewSpending ? t('spendingLabel') : t('savingLabel')) : t('balance'))),
manageBtn(view)),
h('div', { class: 'amt', style: firstLoad ? 'opacity:.3' : '' },
@@ -6770,8 +6777,9 @@ function historyTab() {
wallet.historyLoading ? h('p', { class: 'small muted', style: 'margin:0' }, t('loadingHistory')) : null
);
const featEntries = featureAll('historyEntries', txs, histSel);
- if (!txs.length && !featEntries.length)
- return h('div', { class: 'card' }, h('p', { class: 'muted center', style: 'margin:0' }, t('noTxYet')));
+ // nothing yet: no card at all, it appears with the first payment
+ // (Adam, 2026-11-15: "let's not show an empty history section")
+ if (!txs.length && !featEntries.length) return null;
// Transactions and feature entries merge into one timeline.
const entries = [
diff --git a/src/style.css b/src/style.css
index cd17b48..2bbf8fc 100644
--- a/src/style.css
+++ b/src/style.css
@@ -2195,3 +2195,4 @@ html:has(.call-overlay:not(.call-min)) { overflow: hidden; scrollbar-gutter: aut
.balance-settings-row .bs-text { flex: 1; gap: 3px; min-width: 0; }
.balance-settings-row .bs-title { font-weight: 600; }
.balance-settings-row .bs-tail { color: var(--muted); font-size: 20px; line-height: 1; flex-shrink: 0; width: 14px; text-align: center; }
+.settings-prefs select { flex: 1 1 0; min-width: 0; }
diff --git a/tools/chat-layout-test.js b/tools/chat-layout-test.js
index 7c79858..a0f00ad 100644
--- a/tools/chat-layout-test.js
+++ b/tools/chat-layout-test.js
@@ -164,7 +164,7 @@ try {
console.log('\n[direct messages]');
await page.click('.chat-back');
await sleep(500);
- check('footer returns when the conversation closes', await page.$eval('.footer', (el) => getComputedStyle(el).display !== 'none'));
+ // (no footer to bring back: with a wallet open the pickers live in Settings, 2026-11-15)
await click('button', 'New message');
await setInput('input[placeholder*="npub" i]', '79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798');
await click('button', 'Open');
diff --git a/tools/footer-support-test.js b/tools/footer-support-test.js
index 93ae8a1..0de6c9a 100644
--- a/tools/footer-support-test.js
+++ b/tools/footer-support-test.js
@@ -1,5 +1,5 @@
// "Show your support" lives on Settings → About (2026-11-15: the footer is
-// just the language and currency now) and opens the hat shop; it shows only
+// gone once a wallet is open; language and currency top the Settings hub) and opens the hat shop; it shows only
// once a wallet is open (the shop pays from it).
// Run: bun tools/footer-support-test.js
import puppeteer from './puppeteer.js';
@@ -39,8 +39,11 @@ try {
}
await sleep(1500);
const f = await footerOnly();
- check('the footer is the language and currency alone', f && f.selects === 2 && f.other === 0, JSON.stringify(f));
- await openAbout();
+ check('with a wallet open there is no footer', !f || (await page.$eval('.footer', (el) => getComputedStyle(el).display === 'none')), JSON.stringify(f));
+ await page.evaluate(() => [...document.querySelectorAll('button')].find((e) => e.getAttribute('aria-label') === 'Settings').click()); await sleep(500);
+ check('Settings carries the language and currency', await page.evaluate(() => document.querySelectorAll('.settings-prefs select').length) === 2);
+ if (process.env.SHOT2) await page.screenshot({ path: process.env.SHOT2 });
+ await page.evaluate(() => [...document.querySelectorAll('.settings-tile')].find((e) => /^About/.test(e.textContent.trim())).click()); await sleep(500);
const about = await page.evaluate(() => document.querySelector('.about-card')?.innerText || '');
check('About has the credits, How it works, the theme and the commit', /Adam Soltys/.test(about) && /git\.coinos\.io/.test(about) && /How it works/.test(about) && /(Dark|Light) mode/.test(about) && /Running git commit [0-9a-f]{7}/.test(about), about.replace(/\n/g, ' | '));
check('...and "Show your support"', await link());
diff --git a/tools/signup-quick-test.js b/tools/signup-quick-test.js
index 673319a..d648a70 100644
--- a/tools/signup-quick-test.js
+++ b/tools/signup-quick-test.js
@@ -81,7 +81,7 @@ try {
body: document.body.innerText,
}));
let s = await shape();
- check('in, on Spending alone (no Savings face)', s.faces === 1 && !s.carousel && /spending/i.test(s.label || ''), JSON.stringify({ faces: s.faces, carousel: s.carousel, label: s.label }));
+ check('in, on Spending alone (no Savings face, no name on it)', s.faces === 1 && !s.carousel && !s.label, JSON.stringify({ faces: s.faces, carousel: s.carousel, label: s.label }));
check('a quiet line asks for a way back in', /add a way back into your account/i.test(s.body));
const acct = await page.evaluate(() => JSON.parse(sessionStorage.getItem('btc-wallet-accounts') || '{}'));
const a0 = (acct.accounts || [])[0] || {};