From 82e34f014d654d3a7fa0d049f2f12976bdd4931f Mon Sep 17 00:00:00 2001 From: Nariman Jelveh Date: Thu, 21 May 2026 19:15:21 -0700 Subject: [PATCH] Warn on file:// loads using PuterDialog --- src/puter-js/src/index.js | 33 +++++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/src/puter-js/src/index.js b/src/puter-js/src/index.js index 1a565e56c..e722dbc7a 100644 --- a/src/puter-js/src/index.js +++ b/src/puter-js/src/index.js @@ -18,6 +18,7 @@ import { PTLSSocket } from './modules/networking/PTLS.js'; import { pFetch } from './modules/networking/requests.js'; import OS from './modules/OS.js'; import Perms from './modules/Perms.js'; +import PuterDialog from './modules/PuterDialog.js'; import UI from './modules/UI.js'; import Util from './modules/Util.js'; import { WorkersHandler } from './modules/Workers.js'; @@ -505,6 +506,11 @@ const puterInit = (function () { // Print a CTA for developers to publish their app on the Puter App Store this.printDevCTA(); + + // If the page was opened directly from disk (file:// protocol), + // Puter.js cannot function. Warn the developer immediately on + // load rather than waiting for an action that triggers auth. + this.warnUnsupportedProtocol(); } else if ( this.env === 'web-worker' || this.env === 'service-worker' || this.env === 'nodejs' ) { this.initSubmodules(); } @@ -916,6 +922,33 @@ const puterInit = (function () { ); }; + /** + * Shows the "Unsupported Protocol" warning dialog when the SDK is + * loaded directly from the file:// protocol. Runs once on load (when + * the DOM is ready) so the developer is told to use a web server + * immediately, instead of only when an action triggers the auth flow. + * @private + */ + warnUnsupportedProtocol = function () { + if ( globalThis.location?.protocol !== 'file:' ) return; + if ( this._fileProtocolWarned ) return; + this._fileProtocolWarned = true; + + const showDialog = () => { + // On file:// PuterDialog renders the "Unsupported Protocol" + // warning instead of the auth consent content. + const dialog = new PuterDialog(() => {}, () => {}); + document.body.appendChild(dialog); + dialog.open(); + }; + + if ( document.readyState === 'loading' ) { + document.addEventListener('DOMContentLoaded', showDialog, { once: true }); + } else { + showDialog(); + } + }; + /** * Checks and updates the GUI FS cache for most-commonly used paths * @private