script> (function() { // ---------- Config ---------- const DEFAULT_BACK_TEXT = 'Close'; // change if you want a different default label // Single video config (shared across plans) const SHARED_CONTENT = [ { id: 'welcome', headline: 'Look At You Go!', videoUrl: 'https://player.vimeo.com/video/1145016192?h=1f7fa29654', maxVisits: 3, // backText: 'Close', // aspect: '9/16' // bodyHtml: 'Optional extra HTML content below the video' } ]; const CONTENT_BY_PLAN = { '9d8bee4e-34ed-4438-ae64-878dd047bb66': SHARED_CONTENT, '6225df57-7bf3-4c65-b6f4-2a2c03ec2d56': SHARED_CONTENT, 'da843023-ccd0-4891-becd-cfbe8df0fdb6': SHARED_CONTENT, 'e99cb98c-6658-440e-b363-ca65523c294a': SHARED_CONTENT, '16732d29-0e38-4916-a4bd-bd825e4665a2': SHARED_CONTENT, '1733413b-dbf3-4a0b-9c44-fbcb785ecd95': SHARED_CONTENT, // 'ADD_ANOTHER_PLAN_UUID': SHARED_CONTENT, }; // ---------- Key prefixes (scoped per user) ---------- const PLAN_COUNT_PREFIX = 'welcomePopupCount_forUserPlan_'; const SESSION_SHOWN_PREFIX = 'welcomePopupShown_forUser_'; // ---------- Utils ---------- const readCount = k => (isNaN(parseInt(localStorage.getItem(k),10)) ? 0 : parseInt(localStorage.getItem(k),10)); const incrementCount = k => localStorage.setItem(k, String(readCount(k)+1)); function getUserKey(me){ const parts=[me && (me.uuid||me.user_uuid||me.id), me && (me.email||me.username)].filter(Boolean); return (parts.join('_')||'unknownUser').toLowerCase(); } // ---------- Aspect helpers ---------- function parseAspect(s){ const m = (s||'16/9').match(/^\s*(\d+)\s*\/\s*(\d+)\s*$/); return {w: +m[1], h:+m[2]}; } const aspectToPaddingPercent = ({w,h}) => (h / w) * 100; // ---------- Media helpers ---------- // Keeps Vimeo player URLs (incl. ?h= token) intact; still normalizes watch/short YouTube links. function normalizeEmbedUrl(url){ let u = url; if (u.includes('player.vimeo.com/')) return u; // keep query string if (u.includes('youtube.com/watch?v=')) u = u.replace('watch?v=','embed/'); else if (u.includes('youtu.be/')) u = u.replace('youtu.be/','www.youtube.com/embed/'); else if (u.includes('vimeo.com/')) { const m = /vimeo\.com\/(\d+)/.exec(u); if (m && m[1]) u = 'https://player.vimeo.com/video/' + m[1]; } return u; } // ---------- Render body ---------- function renderPopupBody(pkg) { const ar = parseAspect(pkg.aspect); const padding = aspectToPaddingPercent(ar).toFixed(6); const embedUrl = normalizeEmbedUrl(pkg.videoUrl); const mediaHtml = (embedUrl.includes('youtube.com') || embedUrl.includes('vimeo.com')) ? `` : ``; return `
${mediaHtml}
${pkg.bodyHtml || ''}
`; } // ---------- Post-render enforcement ---------- function enforceEmbedSizing(root=document){ root.querySelectorAll('.ma-embed-AR').forEach(wrap=>{ wrap.style.setProperty('position','relative','important'); wrap.style.setProperty('width','100%','important'); wrap.style.setProperty('height','300px','important'); wrap.style.setProperty('overflow','hidden','important'); const media = wrap.querySelector('.ma-embed-media'); if(media){ media.style.setProperty('position','absolute','important'); media.style.setProperty('top','0','important'); media.style.setProperty('left','0','important'); media.style.setProperty('width','100%','important'); media.style.setProperty('height','100%','important'); media.style.setProperty('border','0','important'); media.style.setProperty('display','block','important'); media.style.setProperty('max-width','none','important'); media.style.setProperty('max-height','none','important'); media.removeAttribute('width'); media.removeAttribute('height'); } }); } // ---------- Relax popup body height (fixes 376px cap) ---------- function relaxPopupHeight() { const sel = '.gc-popup-dynamic-message .gc-popup__dialog .gc-popup__content .gc-popup-sub-text-body.gc-popup-dynamic-message__description'; const el = document.querySelector(sel); if (!el) return; el.style.setProperty('height', 'auto', 'important'); el.style.setProperty('max-height', 'calc(100vh - 220px)', 'important'); el.style.setProperty('overflow', 'visible', 'important'); el.style.setProperty('overflow-x', 'visible', 'important'); el.style.setProperty('width', '100%', 'important'); el.style.setProperty('max-width', 'none', 'important'); } // ---------- Back button label & styling helper (bold +2px, no size change) ---------- function renameBackButton(text, attempts = 10, sizeDeltaPx = 2) { const root = document.querySelector('.gc-popup-dynamic-message'); const footer = root && root.querySelector('.gc-popup__dialog .gc-popup__footer'); if (!footer) { if (attempts > 0) setTimeout(() => renameBackButton(text, attempts - 1, sizeDeltaPx), 60); return; } let btn = Array.from(footer.querySelectorAll('button, a[role="button"], a.gc-button, .gc-button, input[type="button"], input[type="submit"]')) .find(el => /back|close/i.test((el.value || el.textContent || '').trim())); if (!btn) btn = footer.querySelector('button, a[role="button"], a.gc-button, .gc-button, input[type="button"], input[type="submit"]'); if (!btn) { if (attempts > 0) setTimeout(() => renameBackButton(text, attempts - 1, sizeDeltaPx), 60); return; } if (btn.tagName === 'INPUT') { btn.value = text; } else { const labelSpan = btn.querySelector('span, .gc-button__text'); if (labelSpan) labelSpan.textContent = text; else btn.textContent = text; } btn.setAttribute('aria-label', text); const labelEl = btn.querySelector('span, .gc-button__text') || btn; const cs = window.getComputedStyle(labelEl); const baseSize = parseFloat(cs.fontSize) || 16; labelEl.style.setProperty('font-size', (baseSize + sizeDeltaPx) + 'px', 'important'); labelEl.style.setProperty('font-weight', '700', 'important'); labelEl.style.setProperty('line-height', cs.lineHeight, 'important'); } // ---------- NLAF popup ---------- function showViaNLAF(userKey, planUuid, popup) { // Count is per user + plan + popup id const visitKey = PLAN_COUNT_PREFIX + userKey + '_' + planUuid + '_' + popup.id; const count = readCount(visitKey); if (count >= popup.maxVisits) return; // stop after 5 incrementCount(visitKey); const sessionKey = SESSION_SHOWN_PREFIX + userKey; sessionStorage.setItem(sessionKey, 'true'); const fullBody = renderPopupBody(popup); setTimeout(() => { NLAF.showDynamicContentPopup('/dashboard', popup.headline, null, fullBody); setTimeout(() => { const modal = document.querySelector('.gc-popup-dynamic-message__description'); modal && enforceEmbedSizing(modal); relaxPopupHeight(); renameBackButton(popup.backText || DEFAULT_BACK_TEXT); }, 100); }, 2050); } function findMatchingPlan(subs){ for (let i=0;i fetch('/api/me', { method:'GET', credentials:'include', headers:{ 'Accept':'application/json', 'Authorization':'Bearer '+token } })) .then(res => res.ok ? res.json() : {}) .catch(() => ({})); } // ---------- Boot ---------- document.addEventListener('app-ready', () => { if (window.location.pathname !== '/dashboard') return; fetchMe().then(me => { const subs = me.subscriptions || []; const planUuid = findMatchingPlan(subs); if (!planUuid) return; const userKey = getUserKey(me); const sessionKey = SESSION_SHOWN_PREFIX + userKey; // Only once per session if (sessionStorage.getItem(sessionKey)) return; const popupList = CONTENT_BY_PLAN[planUuid] || []; const popup = popupList[0]; // our single shared video if (!popup) return; showViaNLAF(userKey, planUuid, popup); }); }); })();