app
Widget Registry
Public Made by Adomby adom
The reviewed registry of widgets renderable from plain markdown on any wiki page
← Commit history
adom-video: private video blocked in the frame (third-party cookies) -> clear message + Play it in a new tab; F opens the file itself after a failure
1 file changed
+24−4
widgets/video-widget.js+24−4@@ -184,7 +184,15 @@ @keyframes sp{to{transform:rotate(360deg)}} .err{position:absolute;inset:0;display:none;align-items:center;justify-content:center;text-align:center;padding:24px;background:#111;font-size:14px;line-height:1.5} .err.on{display:flex}+ .failed .chrome,.failed .grad,.failed .big,.failed .top{display:none}+ .err{z-index:8} .err code{background:rgba(255,255,255,.1);padding:1px 5px;border-radius:4px;word-break:break-all}+ .err>div{display:flex;flex-direction:column;align-items:center;gap:14px;max-width:560px}+ .errt{font-size:17px;font-weight:600}+ .errbtn{display:inline-flex;align-items:center;gap:8px;padding:10px 18px;border-radius:22px;background:var(--accent);color:#04201e;font-weight:600}+ .errbtn svg{fill:#04201e}+ .errbtn:hover{background:var(--accent-hi)}+ .errn{opacity:.75;font-size:13px} /* captions */ .caps{position:absolute;left:5%;right:5%;bottom:5%;display:flex;flex-wrap:wrap;justify-content:center;pointer-events:none;transition:bottom .25s;z-index:2} .p:not(.hide-ui) .caps{bottom:76px}@@ -341,7 +349,7 @@ this._chapters(); this._captions(); this._volUI(); } - _error(html) { const e = this.$('.err'); e.innerHTML = `<div>${html}</div>`; e.classList.add('on'); this.p.classList.remove('wait'); }+ _error(html) { const e = this.$('.err'); e.innerHTML = `<div>${html}</div>`; e.classList.add('on'); this.p.classList.remove('wait'); this.p.classList.add('failed'); } async _fetchText(u) { const r = await fetch(this._abs(u)).catch(() => null);@@ -553,7 +561,8 @@ popout() { const t = Math.floor(this.v.currentTime); let url;- if (location.pathname.includes('/widget/')) { const u = new URL(location.href); u.searchParams.set('start', String(t)); url = u.href; }+ if (this._failed) url = (this.v.currentSrc || this.v.src).split('#')[0] + `#t=${t}`;+ else if (location.pathname.includes('/widget/')) { const u = new URL(location.href); u.searchParams.set('start', String(t)); url = u.href; } else url = (this.v.currentSrc || this.v.src).split('#')[0] + `#t=${t}`; this.v.pause(); this._openTab(url);@@ -657,9 +666,20 @@ v.addEventListener('waiting', () => p.classList.add('wait')); ['playing', 'canplay', 'seeked', 'pause'].forEach((e) => v.addEventListener(e, () => p.classList.remove('wait'))); v.addEventListener('seeked', () => { this._seekBusy = false; if (this._seekPending != null) { const t = this._seekPending; this._seekPending = null; this._seekBusy = true; v.fastSeek ? v.fastSeek(t) : (v.currentTime = t); } });+ // A private page's video 404s inside the frame when the browser blocks third-party cookies (Safari+ // always, Chrome with that setting): the sandboxed frame is opaque-origin, so the wiki login is not+ // sent. Opened as a page of its own the file request is first-party and plays, with seeking. v.addEventListener('error', () => {- const s = this.getAttribute('video') || this.getAttribute('src') || '';- this._error(`This video could not be loaded.<br><code>${esc(s)}</code><br><br>Check the path is <code>/OWNER/SLUG/render/FILE.mp4</code> and that the file is on the page. On a private page the widget frame may not be signed in.`);+ if (!v.currentSrc && !v.src) return;+ this._failed = true;+ const s = this.getAttribute('video') || (this._manifest() || {}).video || this.getAttribute('src') || '';+ const direct = (v.currentSrc || v.src).split('#')[0];+ this._error(`<div class="errt">This video can't play inside the page</div>+ <button class="errbtn">${svg('play', 20)} Play it in a new tab</button>+ <div class="errn">On a private page, most browsers keep your wiki login out of embedded players, so the+ video is refused here but plays in its own tab. If it fails there too, the file is missing:+ check <code>${esc(s)}</code>.</div>`);+ const b = this.$('.errbtn'); if (b) b.onclick = () => this._openTab(direct + (v.currentTime > 1 ? `#t=${Math.floor(v.currentTime)}` : '')); }); document.addEventListener('fullscreenchange', () => this._sync()); if (v.requestVideoFrameCallback) {