From 94f83c59deefd7d863315f32199e32b80c67af7d Mon Sep 17 00:00:00 2001 From: manjunath22466 <301209272+manjunath22466@users.noreply.github.com> Date: Tue, 15 Sep 2026 23:54:07 +0530 Subject: [PATCH] fix: prevent Nepal media from opening external browsers in Pinokio --- CHANGELOG.md | 4 ++ docs/CURRENT-STATE.md | 8 ++++ src/data/bhoteKoshiEmbeddedMedia.js | 8 +++- src/data/bhoteKoshiEmbeddedMedia.test.mjs | 51 +++++++++++++++++++++++ 4 files changed, 70 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index e4ead0bcd..3ee9dc855 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,9 @@ # Changelog +- Keep Nepal provider media inside the Pinokio compatibility boundary: use + source-linked fallback cards instead of automatic embeds or hidden preloads + that launch an external browser. Ordinary browsers retain embedded playback. + - Extract a portable Director shot runner and connect existing scene playback to it. Preserve authored content, project files, camera/layer behavior and source attribution; document the planned timeline, scene-file and data-pack boundaries. diff --git a/docs/CURRENT-STATE.md b/docs/CURRENT-STATE.md index 70ae1db5d..ca745d3ed 100644 --- a/docs/CURRENT-STATE.md +++ b/docs/CURRENT-STATE.md @@ -11,6 +11,14 @@ Search framing and annotations request semantic map features from an explicit so Nepal media preloads survive repeated camera-flight updates, but Stop, event disable and replacement remove abandoned frames and revoke pending Facebook sessions. Fallback evidence-card clicks respect the shared drawing-tool pointer lease. +In the Pinokio browser shell, Nepal provider embeds and hidden preloads are +disabled before creating frames or loading provider SDKs, because the shell can +redirect iframe navigation to an external browser. Existing source-linked cards +remain available, and Open Original is an explicit action. Optional approved +local clips still use the existing fallback; the public pack bundles no witness +clips. Chrome and Safari retain embeds even when visiting a Pinokio-launched +server. This compatibility fallback does not repair Pinokio's navigation handler. + Nepal flood lines classify the active terrain or photoreal surface, and the surge marker follows that surface. Geographic route coordinates are unchanged; dynamic lines do not rely on unsupported depth-failure materials. Later media-only shots keep their completed source-path history throughout arrival and card reveal. Scene Stop, replacement, seek, and teardown revoke the Upper Valley locator's delayed camera approach and orbit while preserving its visible callout. A revoked timer or camera callback cannot start another flight or interfere with a newer shot. diff --git a/src/data/bhoteKoshiEmbeddedMedia.js b/src/data/bhoteKoshiEmbeddedMedia.js index b00f265a8..d92a4edc0 100644 --- a/src/data/bhoteKoshiEmbeddedMedia.js +++ b/src/data/bhoteKoshiEmbeddedMedia.js @@ -595,7 +595,13 @@ export function createBhoteKoshiEmbeddedMedia({ facebookLoader = loadFacebookSdk, youtubeLoader = loadYouTubeApi, } = {}) { - if (!documentRef?.createElement || !viewer) { + // Pinokio externalizes HTTPS iframe navigation, including hidden preloads. + // Use the existing source-card/local-clip fallback before allocating provider + // resources. Browsers visiting the same Pinokio-launched server keep embeds. + const pinokioShell = /(?:^|\s)Pinokio\/[^\s]+/i.test( + globalRef.navigator?.userAgent || '', + ); + if (pinokioShell || !documentRef?.createElement || !viewer) { return { warm: () => false, show: () => false, diff --git a/src/data/bhoteKoshiEmbeddedMedia.test.mjs b/src/data/bhoteKoshiEmbeddedMedia.test.mjs index 5223fff6c..6829adca5 100644 --- a/src/data/bhoteKoshiEmbeddedMedia.test.mjs +++ b/src/data/bhoteKoshiEmbeddedMedia.test.mjs @@ -10,6 +10,57 @@ import { resolveEmbeddedMediaSource, } from './bhoteKoshiEmbeddedMedia.js'; +test('Pinokio fallback never creates provider DOM or loads SDKs', async () => { + const unexpected = () => { throw new Error('Provider resource allocated in Pinokio'); }; + const media = createBhoteKoshiEmbeddedMedia({ + viewer: {}, + documentRef: { createElement: unexpected }, + globalRef: { + navigator: { userAgent: 'Mozilla/5.0 Chrome/140.0.0.0 Safari/537.36 Pinokio/8.0.40' }, + setTimeout: unexpected, + requestAnimationFrame: unexpected, + }, + facebookLoader: unexpected, + youtubeLoader: unexpected, + xLoader: unexpected, + }); + for (const sourceUrl of [ + 'https://www.youtube.com/watch?v=abcdefghijk', + 'https://www.facebook.com/watch/?v=123456789', + 'https://x.com/example/status/123456789', + ]) { + const options = { observation: { media: { sourceUrl } }, autoplay: true }; + assert.equal(media.warm(options), false, 'no hidden preload'); + assert.equal(media.show(options), false, 'retain the existing fallback card'); + assert.equal(media.play(), false); + assert.equal(media.pause(), false); + media.hide(); + } + media.destroy(); + media.hide(); + await Promise.resolve(); +}); + +test('ordinary browsers retain real preloads on the same launcher URL', () => { + for (const userAgent of [ + 'Mozilla/5.0 Chrome/140.0.0.0 Safari/537.36', + 'Mozilla/5.0 Version/18.0 Safari/605.1.15', + 'Mozilla/5.0 Electron/38.0.0', + '', + ]) { + const { media, root } = preloadFixture({ globalRef: { + navigator: { userAgent }, location: { href: 'http://127.0.0.1:42003/' }, + } }); + assert.equal(media.warm({ observation: { media: { + sourceUrl: 'https://www.youtube.com/watch?v=abcdefghijk', + } } }), true); + assert.equal(root.children.length, 1); + media.pause(); + assert.equal(root.children.length, 0); + media.destroy(); + } +}); + function trimmedPlaybackFixture() { let now = 0; let nextId = 0;