[claude] Session panel QR codes + default 200 sats (#46) (#55)

Co-authored-by: Claude (Opus 4.6) <claude@hermes.local>
Co-committed-by: Claude (Opus 4.6) <claude@hermes.local>
This commit was merged in pull request #55.
This commit is contained in:
2026-03-23 14:52:36 +00:00
committed by rockachopa
parent 1f9822aa11
commit 4712619959
4 changed files with 45 additions and 9 deletions

View File

@@ -576,8 +576,8 @@
<div data-session-step="fund">
<div class="panel-label">DEPOSIT AMOUNT (20010,000 sats)</div>
<div class="session-amount-presets">
<button class="session-amount-btn" data-sats="200">200</button>
<button class="session-amount-btn active" data-sats="500">500</button>
<button class="session-amount-btn active" data-sats="200">200</button>
<button class="session-amount-btn" data-sats="500">500</button>
<button class="session-amount-btn" data-sats="1000">1000</button>
<button class="session-amount-btn" data-sats="2000">2000</button>
<button class="session-amount-btn" data-sats="5000">5000</button>
@@ -585,7 +585,7 @@
</div>
<div class="session-amount-row">
<input type="number" id="session-amount-input" class="session-amount-input"
min="200" max="10000" value="500" step="1" />
min="200" max="10000" value="200" step="1" />
<span>sats</span>
</div>
<button class="panel-btn primary-green" id="session-create-btn" style="margin-top:12px">START SESSION →</button>
@@ -622,8 +622,8 @@
<div data-session-step="topup" style="display:none">
<div class="panel-label">TOPUP AMOUNT (20010,000 sats)</div>
<div class="session-amount-presets">
<button class="session-amount-btn" data-sats="200">200</button>
<button class="session-amount-btn active" data-sats="500">500</button>
<button class="session-amount-btn active" data-sats="200">200</button>
<button class="session-amount-btn" data-sats="500">500</button>
<button class="session-amount-btn" data-sats="1000">1000</button>
<button class="session-amount-btn" data-sats="2000">2000</button>
<button class="session-amount-btn" data-sats="5000">5000</button>
@@ -631,7 +631,7 @@
</div>
<div class="session-amount-row">
<input type="number" id="session-topup-input" class="session-amount-input"
min="200" max="10000" value="500" step="1" />
min="200" max="10000" value="200" step="1" />
<span>sats</span>
</div>
<button class="panel-btn primary-green" id="session-topup-create-btn" style="margin-top:12px">CREATE TOPUP INVOICE →</button>

View File

@@ -16,6 +16,7 @@ import { setSpeechBubble, setMood } from './agents.js';
import { appendSystemMessage, setSessionSendHandler, setInputBarSessionMode } from './ui.js';
import { getOrRefreshToken } from './nostr-identity.js';
import { sentiment } from './edge-worker-client.js';
import qrcode from 'qrcode-generator';
const API = '/api';
const LS_KEY = 'timmy_session_v1';
@@ -31,8 +32,8 @@ let _balanceSats = 0;
let _sessionState = null; // null | 'awaiting_payment' | 'active' | 'paused' | 'expired'
let _pollTimer = null;
let _inFlight = false;
let _selectedSats = 500; // deposit amount selection
let _topupSats = 500; // topup amount selection
let _selectedSats = 200; // deposit amount selection
let _topupSats = 200; // topup amount selection
// ── Public API ────────────────────────────────────────────────────────────────
@@ -238,6 +239,7 @@ async function _createSession() {
const hashEl = _el('session-invoice-hash');
if (hashEl) hashEl.dataset.hash = inv.paymentHash || '';
_renderQR('session-invoice-qr', inv.paymentRequest);
_setStep('invoice');
_setStatus('invoice', '⚡ Awaiting deposit…', '#ffaa00');
@@ -345,6 +347,7 @@ async function _createTopup() {
_el('session-topup-pr').textContent = pending.paymentRequest || '';
const th = _el('session-topup-hash');
if (th) th.dataset.hash = pending.paymentHash || '';
_renderQR('session-topup-qr', pending.paymentRequest);
_el('session-topup-pr-row').style.display = '';
_setStatus('topup', '⚡ Previous invoice still pending', '#ffaa00');
return;
@@ -357,6 +360,7 @@ async function _createTopup() {
_el('session-topup-pr').textContent = inv.paymentRequest || '';
const th = _el('session-topup-hash');
if (th) th.dataset.hash = inv.paymentHash || '';
_renderQR('session-topup-qr', inv.paymentRequest);
_el('session-topup-pr-row').style.display = '';
_setStatus('topup', '⚡ Awaiting topup payment…', '#ffaa00');
@@ -566,6 +570,30 @@ function _clearError() {
if (el) el.textContent = '';
}
function _renderQR(containerId, data) {
const el = _el(containerId);
if (!el || !data) return;
try {
const qr = qrcode(0, 'L');
qr.addData(data.toUpperCase());
qr.make();
el.innerHTML = qr.createSvgTag({ scalable: true });
el.style.height = 'auto';
el.style.padding = '8px';
// Style the SVG to fit
const svg = el.querySelector('svg');
if (svg) {
svg.style.width = '100%';
svg.style.maxWidth = '200px';
svg.style.height = 'auto';
svg.style.display = 'block';
svg.style.margin = '0 auto';
}
} catch {
el.textContent = '[ QR ]';
}
}
function _stopPolling() {
clearTimeout(_pollTimer);
_pollTimer = null;

View File

@@ -10,10 +10,11 @@
"dependencies": {
"@xenova/transformers": "^2.17.2",
"nostr-tools": "^2.23.3",
"qrcode-generator": "^1.4.4",
"three": "0.171.0"
},
"devDependencies": {
"vite": "^5.4.0"
"vite": "^5.4.15"
}
},
"node_modules/@esbuild/aix-ppc64": {
@@ -1617,6 +1618,12 @@
"once": "^1.3.1"
}
},
"node_modules/qrcode-generator": {
"version": "1.4.4",
"resolved": "https://registry.npmjs.org/qrcode-generator/-/qrcode-generator-1.4.4.tgz",
"integrity": "sha512-HM7yY8O2ilqhmULxGMpcHSF1EhJJ9yBj8gvDEuZ6M+KGJ0YY2hKpnXvRD+hZPLrDVck3ExIGhmPtSdcjC+guuw==",
"license": "MIT"
},
"node_modules/rc": {
"version": "1.2.8",
"resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz",

View File

@@ -11,6 +11,7 @@
"dependencies": {
"@xenova/transformers": "^2.17.2",
"nostr-tools": "^2.23.3",
"qrcode-generator": "^1.4.4",
"three": "0.171.0"
},
"devDependencies": {