Wall view interaction: click banner, countdown, then a viewed checkmark (per-position, persisted)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
@@ -365,6 +365,11 @@ textarea{resize:vertical;font:inherit}
|
|||||||
.wall-card{background:var(--panel);border:1px solid var(--line);border-radius:var(--radius);padding:16px;text-align:center}
|
.wall-card{background:var(--panel);border:1px solid var(--line);border-radius:var(--radius);padding:16px;text-align:center}
|
||||||
.wall-card img{max-width:100%;border-radius:10px;border:1px solid var(--line-strong)}
|
.wall-card img{max-width:100%;border-radius:10px;border:1px solid var(--line-strong)}
|
||||||
.wall-pos{font-family:var(--mono);font-size:11px;color:var(--muted);text-transform:uppercase;letter-spacing:.08em;margin-bottom:8px}
|
.wall-pos{font-family:var(--mono);font-size:11px;color:var(--muted);text-transform:uppercase;letter-spacing:.08em;margin-bottom:8px}
|
||||||
|
.wc-creative img{max-width:100%;border-radius:10px;border:1px solid var(--line-strong)}
|
||||||
|
.wc-action{margin-top:10px;min-height:32px;display:flex;justify-content:center;align-items:center}
|
||||||
|
.wc-check{color:var(--mint);font-weight:800;border:1px solid var(--mint);border-radius:999px;padding:4px 14px;
|
||||||
|
box-shadow:0 0 14px rgba(67,232,195,.3)}
|
||||||
|
.wc-timer{color:var(--amber);font-weight:700;font-family:var(--mono);font-size:13px}
|
||||||
/* ── modal (sponsor message) ── */
|
/* ── modal (sponsor message) ── */
|
||||||
.modal-back{position:fixed;inset:0;z-index:100;background:rgba(2,6,5,.72);display:flex;align-items:center;justify-content:center;padding:20px}
|
.modal-back{position:fixed;inset:0;z-index:100;background:rgba(2,6,5,.72);display:flex;align-items:center;justify-content:center;padding:20px}
|
||||||
.modal-card{background:var(--panel-solid);border:1px solid var(--line-strong);border-radius:var(--radius);
|
.modal-card{background:var(--panel-solid);border:1px solid var(--line-strong);border-radius:var(--radius);
|
||||||
|
|||||||
+33
-5
@@ -20,19 +20,47 @@
|
|||||||
if (w.qrUrl) IAP.$('bioQr').src = w.qrUrl;
|
if (w.qrUrl) IAP.$('bioQr').src = w.qrUrl;
|
||||||
IAP.$('wallCtaHead').textContent = 'Join ' + w.name + '’s line';
|
IAP.$('wallCtaHead').textContent = 'Join ' + w.name + '’s line';
|
||||||
IAP.$('wallJoin').href = w.joinUrl;
|
IAP.$('wallJoin').href = w.joinUrl;
|
||||||
|
// per-wall viewed-position memory (survives revisits; anonymous-friendly)
|
||||||
|
const VKEY = 'iap-wall-' + name;
|
||||||
|
let viewed = {};
|
||||||
|
try { viewed = JSON.parse(localStorage.getItem(VKEY) || '{}'); } catch (e) {}
|
||||||
|
const DWELL = 10;
|
||||||
const grid = IAP.$('wallGrid');
|
const grid = IAP.$('wallGrid');
|
||||||
grid.innerHTML = '';
|
grid.innerHTML = '';
|
||||||
w.ladder.forEach((m, i) => {
|
w.ladder.forEach((m, i) => {
|
||||||
const d = document.createElement('div');
|
const d = document.createElement('div');
|
||||||
d.className = 'wall-card';
|
d.className = 'wall-card';
|
||||||
const safe = String(m.name || 'member').replace(/[&<>]/g, '');
|
const safe = String(m.name || 'member').replace(/[&<>]/g, '');
|
||||||
|
const creative = m.bannerUrl
|
||||||
|
? '<img src="' + m.bannerUrl + '" alt="' + safe + ' banner">'
|
||||||
|
: '<b>' + safe + '</b><br><span class="muted small">' + (m.targetUrl ? 'visit their site' : 'banner slot open') + '</span>';
|
||||||
d.innerHTML = '<div class="wall-pos">Position ' + (i + 1) + (i === 0 ? ' · this wall' : '') + '</div>'
|
d.innerHTML = '<div class="wall-pos">Position ' + (i + 1) + (i === 0 ? ' · this wall' : '') + '</div>'
|
||||||
+ (m.bannerUrl
|
+ '<div class="wc-creative">' + creative + '</div>'
|
||||||
? '<a href="' + m.targetUrl + '" target="_blank" rel="noopener nofollow"><img src="' + m.bannerUrl + '" alt="' + safe + ' banner"></a>'
|
+ '<div class="wc-action"></div>'
|
||||||
: m.targetUrl
|
|
||||||
? '<a href="' + m.targetUrl + '" target="_blank" rel="noopener nofollow"><b>' + safe + '</b><br><span class="muted small">visit their site</span></a>'
|
|
||||||
: '<b>' + safe + '</b><br><span class="muted small">banner slot open</span>')
|
|
||||||
+ '<div class="small muted" style="margin-top:8px">' + safe + '</div>';
|
+ '<div class="small muted" style="margin-top:8px">' + safe + '</div>';
|
||||||
|
const act = d.querySelector('.wc-action');
|
||||||
|
const done = () => { act.innerHTML = '<span class="wc-check">✓ viewed</span>'; };
|
||||||
|
if (!m.targetUrl) { act.innerHTML = '<span class="muted small">no ad yet</span>'; }
|
||||||
|
else if (viewed[i]) { done(); }
|
||||||
|
else {
|
||||||
|
const btn = document.createElement('button');
|
||||||
|
btn.className = 'btn small'; btn.textContent = 'View this ad';
|
||||||
|
btn.addEventListener('click', () => {
|
||||||
|
window.open(m.targetUrl, '_blank'); // real visit to the advertiser
|
||||||
|
let left = DWELL;
|
||||||
|
btn.disabled = true;
|
||||||
|
act.innerHTML = '<span class="wc-timer">Viewing… ' + left + 's</span>';
|
||||||
|
const t = setInterval(() => {
|
||||||
|
left--;
|
||||||
|
if (left > 0) { act.querySelector('.wc-timer').textContent = 'Viewing… ' + left + 's'; return; }
|
||||||
|
clearInterval(t);
|
||||||
|
viewed[i] = 1;
|
||||||
|
try { localStorage.setItem(VKEY, JSON.stringify(viewed)); } catch (e) {}
|
||||||
|
done();
|
||||||
|
}, 1000);
|
||||||
|
});
|
||||||
|
act.appendChild(btn);
|
||||||
|
}
|
||||||
grid.appendChild(d);
|
grid.appendChild(d);
|
||||||
});
|
});
|
||||||
})();
|
})();
|
||||||
|
|||||||
@@ -5,7 +5,7 @@
|
|||||||
<title>The contract | InstantAdPay</title>
|
<title>The contract | InstantAdPay</title>
|
||||||
<meta name="description" content="Plain-language review of the InstantAdPay settlement contract: what it does, what nobody can change, what the operator can and cannot touch, and how to verify all of it yourself.">
|
<meta name="description" content="Plain-language review of the InstantAdPay settlement contract: what it does, what nobody can change, what the operator can and cannot touch, and how to verify all of it yourself.">
|
||||||
<link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Sora:wght@600;700;800&display=swap">
|
<link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Sora:wght@600;700;800&display=swap">
|
||||||
<link rel="stylesheet" href="/assets/site.css?v=20260906d">
|
<link rel="stylesheet" href="/assets/site.css?v=20260906e">
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<div class="wrap">
|
<div class="wrap">
|
||||||
@@ -129,8 +129,8 @@
|
|||||||
<div class="small">Advertising services with a performance referral program. Not an investment product; no income guarantees. Crypto transactions are irreversible. Never spend what you cannot afford.</div>
|
<div class="small">Advertising services with a performance referral program. Not an investment product; no income guarantees. Crypto transactions are irreversible. Never spend what you cannot afford.</div>
|
||||||
</footer>
|
</footer>
|
||||||
</div>
|
</div>
|
||||||
<script src="/assets/common.js?v=20260906d"></script>
|
<script src="/assets/common.js?v=20260906e"></script>
|
||||||
<script src="/assets/contract.js?v=20260906d"></script>
|
<script src="/assets/contract.js?v=20260906e"></script>
|
||||||
<script src="/assets/chat.js?v=20260906d"></script>
|
<script src="/assets/chat.js?v=20260906e"></script>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|||||||
+5
-5
@@ -5,7 +5,7 @@
|
|||||||
<title>InstantAdPay: advertise and earn, locked in code</title>
|
<title>InstantAdPay: advertise and earn, locked in code</title>
|
||||||
<meta name="description" content="Real ad packages with instant on-chain settlement. Every purchase pays the sponsor line in the same transaction, verifiable by anyone on the live ledger.">
|
<meta name="description" content="Real ad packages with instant on-chain settlement. Every purchase pays the sponsor line in the same transaction, verifiable by anyone on the live ledger.">
|
||||||
<link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Sora:wght@600;700;800&display=swap">
|
<link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Sora:wght@600;700;800&display=swap">
|
||||||
<link rel="stylesheet" href="/assets/site.css?v=20260906d">
|
<link rel="stylesheet" href="/assets/site.css?v=20260906e">
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
|
|
||||||
@@ -410,9 +410,9 @@
|
|||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
<script src="/assets/common.js?v=20260906d"></script>
|
<script src="/assets/common.js?v=20260906e"></script>
|
||||||
<script src="/assets/wallet.js?v=20260906d"></script>
|
<script src="/assets/wallet.js?v=20260906e"></script>
|
||||||
<script src="/assets/home.js?v=20260906d"></script>
|
<script src="/assets/home.js?v=20260906e"></script>
|
||||||
<script src="/assets/chat.js?v=20260906d"></script>
|
<script src="/assets/chat.js?v=20260906e"></script>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|||||||
+4
-4
@@ -5,7 +5,7 @@
|
|||||||
<title>Live ledger | InstantAdPay</title>
|
<title>Live ledger | InstantAdPay</title>
|
||||||
<meta name="description" content="Every purchase, payout, and pass-up on InstantAdPay, streamed straight from the blockchain with a verify link on every line.">
|
<meta name="description" content="Every purchase, payout, and pass-up on InstantAdPay, streamed straight from the blockchain with a verify link on every line.">
|
||||||
<link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Sora:wght@600;700;800&display=swap">
|
<link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Sora:wght@600;700;800&display=swap">
|
||||||
<link rel="stylesheet" href="/assets/site.css?v=20260906d">
|
<link rel="stylesheet" href="/assets/site.css?v=20260906e">
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<div class="wrap">
|
<div class="wrap">
|
||||||
@@ -25,8 +25,8 @@
|
|||||||
<div>InstantAdPay · <a href="/">how it works</a> · <a id="contractLink" href="#" target="_blank" rel="noopener">contract source ↗</a></div>
|
<div>InstantAdPay · <a href="/">how it works</a> · <a id="contractLink" href="#" target="_blank" rel="noopener">contract source ↗</a></div>
|
||||||
</footer>
|
</footer>
|
||||||
</div>
|
</div>
|
||||||
<script src="/assets/common.js?v=20260906d"></script>
|
<script src="/assets/common.js?v=20260906e"></script>
|
||||||
<script src="/assets/ledger.js?v=20260906d"></script>
|
<script src="/assets/ledger.js?v=20260906e"></script>
|
||||||
<script src="/assets/chat.js?v=20260906d"></script>
|
<script src="/assets/chat.js?v=20260906e"></script>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|||||||
+5
-5
@@ -4,7 +4,7 @@
|
|||||||
<meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1">
|
<meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1">
|
||||||
<title>Member area | InstantAdPay</title>
|
<title>Member area | InstantAdPay</title>
|
||||||
<link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Sora:wght@600;700;800&display=swap">
|
<link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Sora:wght@600;700;800&display=swap">
|
||||||
<link rel="stylesheet" href="/assets/site.css?v=20260906d">
|
<link rel="stylesheet" href="/assets/site.css?v=20260906e">
|
||||||
</head>
|
</head>
|
||||||
<body class="bo-body">
|
<body class="bo-body">
|
||||||
|
|
||||||
@@ -555,9 +555,9 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<script src="/assets/common.js?v=20260906d"></script>
|
<script src="/assets/common.js?v=20260906e"></script>
|
||||||
<script src="/assets/wallet.js?v=20260906d"></script>
|
<script src="/assets/wallet.js?v=20260906e"></script>
|
||||||
<script src="/assets/my.js?v=20260906d"></script>
|
<script src="/assets/my.js?v=20260906e"></script>
|
||||||
<script src="/assets/chat.js?v=20260906d"></script>
|
<script src="/assets/chat.js?v=20260906e"></script>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|||||||
+3
-3
@@ -4,7 +4,7 @@
|
|||||||
<meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1">
|
<meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1">
|
||||||
<title>Transaction | InstantAdPay</title>
|
<title>Transaction | InstantAdPay</title>
|
||||||
<link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Sora:wght@600;700;800&display=swap">
|
<link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Sora:wght@600;700;800&display=swap">
|
||||||
<link rel="stylesheet" href="/assets/site.css?v=20260906d">
|
<link rel="stylesheet" href="/assets/site.css?v=20260906e">
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<div id="nav"></div>
|
<div id="nav"></div>
|
||||||
@@ -33,7 +33,7 @@
|
|||||||
<p><a href="/ledger">← Back to the live ledger</a> · <a href="/contract">Read the contract review</a></p>
|
<p><a href="/ledger">← Back to the live ledger</a> · <a href="/contract">Read the contract review</a></p>
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
<script src="/assets/common.js?v=20260906d"></script>
|
<script src="/assets/common.js?v=20260906e"></script>
|
||||||
<script src="/assets/tx.js?v=20260906d"></script>
|
<script src="/assets/tx.js?v=20260906e"></script>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|||||||
+2
-2
@@ -4,7 +4,7 @@
|
|||||||
<meta charset="utf-8">
|
<meta charset="utf-8">
|
||||||
<meta name="viewport" content="width=device-width,initial-scale=1">
|
<meta name="viewport" content="width=device-width,initial-scale=1">
|
||||||
<title>Viewing ad — InstantAdPay</title>
|
<title>Viewing ad — InstantAdPay</title>
|
||||||
<link rel="stylesheet" href="/assets/site.css?v=20260906d">
|
<link rel="stylesheet" href="/assets/site.css?v=20260906e">
|
||||||
<style>
|
<style>
|
||||||
html,body{height:100%;margin:0;overflow:hidden}
|
html,body{height:100%;margin:0;overflow:hidden}
|
||||||
.vw{display:flex;flex-direction:column;height:100vh;height:100dvh;background:var(--bg,#04110c);color:var(--ink,#e8fff7)}
|
.vw{display:flex;flex-direction:column;height:100vh;height:100dvh;background:var(--bg,#04110c);color:var(--ink,#e8fff7)}
|
||||||
@@ -43,6 +43,6 @@
|
|||||||
</div>
|
</div>
|
||||||
<iframe class="vframe" id="vFrame" sandbox="allow-scripts allow-same-origin allow-forms allow-popups" referrerpolicy="no-referrer" title="Advertiser site"></iframe>
|
<iframe class="vframe" id="vFrame" sandbox="allow-scripts allow-same-origin allow-forms allow-popups" referrerpolicy="no-referrer" title="Advertiser site"></iframe>
|
||||||
</div>
|
</div>
|
||||||
<script src="/assets/view.js?v=20260906d"></script>
|
<script src="/assets/view.js?v=20260906e"></script>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|||||||
+3
-3
@@ -4,7 +4,7 @@
|
|||||||
<meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1">
|
<meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1">
|
||||||
<title>Banner wall | InstantAdPay</title>
|
<title>Banner wall | InstantAdPay</title>
|
||||||
<link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Sora:wght@600;700;800&display=swap">
|
<link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Sora:wght@600;700;800&display=swap">
|
||||||
<link rel="stylesheet" href="/assets/site.css?v=20260906d">
|
<link rel="stylesheet" href="/assets/site.css?v=20260906e">
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<div id="nav"></div>
|
<div id="nav"></div>
|
||||||
@@ -34,7 +34,7 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
<script src="/assets/common.js?v=20260906d"></script>
|
<script src="/assets/common.js?v=20260906e"></script>
|
||||||
<script src="/assets/wall.js?v=20260906d"></script>
|
<script src="/assets/wall.js?v=20260906e"></script>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|||||||
Reference in New Issue
Block a user