Ad viewing: full-screen in-page overlay instead of a new tab
Mobile and in-app wallet (dApp) browsers handle tabs badly, so opening each ad in a new tab made the earn loop hard to navigate and impossible to close. Ads now open in a full-screen in-page overlay that reuses the /view dwell + human-check + credit logic in an iframe: an always-working close control, no window.close, no tab-switching. The framed /view relaxes its focus-pause to visibility only and messages the dashboard when it credits or the user is done. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
+32
-4
@@ -1280,12 +1280,40 @@
|
||||
: 'No member ads are live in rotation right now. Views resume the moment a campaign is running.') + '</span>';
|
||||
return;
|
||||
}
|
||||
const w = window.open(r.viewUrl, '_blank');
|
||||
box.innerHTML = '<span class="muted small">Ad open in its own tab. Watch the countdown, pass the quick '
|
||||
+ 'check, and the view credits itself — this page updates the moment it does.</span>'
|
||||
+ (w ? '' : '<br><a href="' + r.viewUrl + '" target="_blank" rel="noopener">Pop-up blocked — open the ad here.</a>');
|
||||
openAdOverlay(r.viewUrl);
|
||||
box.innerHTML = '<span class="muted small">Watch the countdown and pass the quick check. Your view credits itself and this page updates right away.</span>';
|
||||
$('earnStartBtn').textContent = 'View next ad';
|
||||
}
|
||||
// In-page ad overlay: no new tab (mobile and in-app wallet browsers handle tabs
|
||||
// badly), no window.close needed. The /view page runs the dwell + check inside,
|
||||
// messages back when it credits or when the user is done.
|
||||
function openAdOverlay(url) {
|
||||
closeAdOverlay();
|
||||
const back = document.createElement('div');
|
||||
back.id = 'adOverlay';
|
||||
back.style.cssText = 'position:fixed;inset:0;z-index:100000;background:#050b09;display:flex;flex-direction:column';
|
||||
const x = document.createElement('button');
|
||||
x.type = 'button'; x.setAttribute('aria-label', 'Close ad');
|
||||
x.textContent = '✕';
|
||||
x.style.cssText = 'position:absolute;top:10px;right:12px;z-index:2;width:40px;height:40px;border-radius:50%;border:1px solid rgba(255,255,255,.25);background:rgba(6,10,16,.85);color:#fff;font-size:20px;font-weight:700;cursor:pointer';
|
||||
x.addEventListener('click', closeAdOverlay);
|
||||
const ifr = document.createElement('iframe');
|
||||
ifr.src = url;
|
||||
ifr.style.cssText = 'flex:1;width:100%;border:0;background:#050b09';
|
||||
back.appendChild(ifr); back.appendChild(x);
|
||||
document.body.appendChild(back);
|
||||
document.body.style.overflow = 'hidden';
|
||||
}
|
||||
function closeAdOverlay() {
|
||||
const m = $('adOverlay'); if (m) m.remove();
|
||||
document.body.style.overflow = '';
|
||||
earnRefresh(); loadDashboard();
|
||||
}
|
||||
window.addEventListener('message', e => {
|
||||
if (e.origin !== location.origin || !e.data) return;
|
||||
if (e.data.t === 'iap-view-close') closeAdOverlay();
|
||||
else if (e.data.t === 'iap-view-done') { earnRefresh(); loadDashboard(); }
|
||||
});
|
||||
$('earnStartBtn').addEventListener('click', () => earnShowAd());
|
||||
// the viewer tab pings localStorage when a view credits; refresh instantly
|
||||
window.addEventListener('storage', e => {
|
||||
|
||||
Reference in New Issue
Block a user