Earn: video stops when leaving the tab/pane, 'all watched today' message, open earn tokens survive a redeploy; admin member search matches as you type, clearer old-site line; QA earn harness follows the done screen

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This commit is contained in:
martbost
2026-09-13 06:46:08 -05:00
parent 0c7f957db4
commit 4efba20d4e
7 changed files with 85 additions and 16 deletions
+17 -2
View File
@@ -513,6 +513,7 @@
IAP.adSlot('text', 'adStripTop');
if ($('adSlotPane-' + name)) IAP.adSlot('banner', 'adSlotPane-' + name);
if (name === 'earn') setEarnSub(earnSub); // refresh whichever sub-tab is active
else if (vidState.token) stopVideo();
if (name === 'profile') loadLineBanner();
if (name === 'line') { loadLineage(); loadUplineMessages(); loadCoach(); loadLinkStats(); loadProspects(); }
if (name === 'campaigns') ['cTarget', 'cImage', 'cVideoUrl'].forEach(id => { if ($(id)) $(id).value = ''; }); // no residual URL between visits
@@ -989,13 +990,26 @@
$('vidStartBtn').hidden = false;
} catch (e) {}
}
// leaving the player (other sub-tab, other pane, page hidden) stops the clip: nothing plays or earns in the background (Marty, 2026-09-13)
function stopVideo() {
const p = $('vidPlayer'); if (!p) return;
const was = !!vidState.token && !vidState.done;
try { p.pause(); p.ontimeupdate = null; p.onseeking = null; p.removeAttribute('src'); p.load(); } catch (e) {}
vidState.token = null; vidState.done = false; vidState.credited = false; vidState.maxSeen = 0;
if ($('vidWrap')) $('vidWrap').hidden = true;
if ($('vidBox')) { $('vidBox').hidden = false; if (was) $('vidBox').innerHTML = '<span class="muted small">Video stopped when you left the tab. Tap Load a video to start a fresh one.</span>'; }
if ($('vidStartBtn')) { $('vidStartBtn').disabled = false; $('vidStartBtn').textContent = 'Load a video'; }
}
document.addEventListener('visibilitychange', () => { if (document.hidden && vidState.token && !vidState.done) stopVideo(); });
async function loadVideoAd() {
let r = null;
try { r = await (await fetch('/api/my/videos?orientation=landscape')).json(); } catch (e) {}
if (!r || !r.ad) {
$('vidBox').innerHTML = '<span class="muted small">' + (r && r.status && r.status.left <= 0
? 'That is today\'s video set. Come back tomorrow.'
: r && r.allWatched ? 'You have watched every live video for today (each one pays once a day). New ones appear as members launch video campaigns.'
: 'No member videos are live right now. Check back when a campaign is running.') + '</span>';
$('vidBox').hidden = false;
$('vidWrap').hidden = true;
return;
}
@@ -1029,10 +1043,10 @@
try {
const r = await (await fetch('/api/my/videowatch', { method: 'POST',
headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ token: vidState.token }) })).json();
if (r.error) { IAP.status(r.error, 'bad'); $('vidHint').textContent = r.error; }
if (r.error) { IAP.status(r.error, 'bad'); $('vidHint').textContent = r.error + (/no longer open|stale/.test(r.error) ? ' Loading a fresh one.' : ''); if (/no longer open|stale/.test(r.error)) setTimeout(() => loadVideoAd(), 1200); }
else if (r.credited) { IAP.status('+' + r.credited + ' credits earned for watching.', 'ok'); $('vidHint').textContent = '+' + r.credited + ' credits earned. Load the next one.'; loadDashboard(); }
else $('vidHint').textContent = 'That video just ran out of budget — load another.';
$('vidProgress').textContent = 'today: ' + ((r.status && r.status.count) || 0) + ' / ' + ((r.status && r.status.cap) || 0) + ' videos watched';
if (r.status) $('vidProgress').textContent = 'today: ' + (r.status.count || 0) + ' / ' + r.status.cap + ' videos watched';
} catch (e) { IAP.status('Could not confirm that watch. Try the next one.', 'bad'); }
$('vidStartBtn').disabled = false;
$('vidStartBtn').textContent = 'Next video';
@@ -1305,6 +1319,7 @@
let earnSub = 'watch';
function setEarnSub(which) {
earnSub = ['inbox', 'videos', 'visits'].includes(which) ? which : 'watch';
if (earnSub !== 'videos' && vidState.token) stopVideo();
const w = $('earn-watch'), i = $('earn-inbox'), v = $('earn-videos'), vs = $('earn-visits');
if (w) w.hidden = earnSub !== 'watch';
if (i) i.hidden = earnSub !== 'inbox';