diff --git a/src/puter-js/src/lib/utils.js b/src/puter-js/src/lib/utils.js index 61e796903..c817c31ee 100644 --- a/src/puter-js/src/lib/utils.js +++ b/src/puter-js/src/lib/utils.js @@ -1,5 +1,6 @@ -import { FileReaderPoly } from "./polyfills/fileReaderPoly.js"; -import { showUsageLimitDialog } from "../modules/UsageLimitDialog.js"; +import { FileReaderPoly } from './polyfills/fileReaderPoly.js'; +import { showUsageLimitDialog } from '../modules/UsageLimitDialog.js'; +import { showEmailConfirmationDialog } from '../modules/EmailConfirmationDialog.js'; /** * Parses a given response text into a JSON object. If the parsing fails due to invalid JSON format, @@ -394,6 +395,10 @@ async function driverCall_ ( showUsageLimitDialog('You have reached your usage limit for this account.Please upgrade to continue.'); } } + // Check for email confirmation required (e.g. AI calls) + if ( lineObject?.error?.code === 'email_must_be_confirmed' && puter.env === 'web' ) { + showEmailConfirmationDialog(lineObject?.error?.message || 'Email confirmation required. Go to Puter.com to confirm your email address.'); + } if ( typeof (lineObject.text) === 'string' ) { Object.defineProperty(lineObject, 'toString', { @@ -481,6 +486,11 @@ async function driverCall_ ( showUsageLimitDialog('Your account has not enough funding to complete this request.Please upgrade to continue.'); } + // Check for email confirmation required (e.g. AI calls) - web only + if ( resp?.error?.code === 'email_must_be_confirmed' && puter.env === 'web' ) { + showEmailConfirmationDialog(resp?.error?.message || 'Email confirmation required. Go to Puter.com to confirm your email address.'); + } + // HTTP Error - unauthorized if ( response.status === 401 || resp?.code === 'token_auth_failed' ) { if ( resp?.code === 'token_auth_failed' && puter.env === 'web' ) { @@ -612,5 +622,5 @@ function arrayBufferToDataUri (arrayBuffer) { } export { - arrayBufferToDataUri, blob_to_url, blobToDataUri, driverCall, handle_error, handle_resp, initXhr, make_driver_method, parseResponse, setupXhrEventHandlers, uuidv4 + arrayBufferToDataUri, blob_to_url, blobToDataUri, driverCall, handle_error, handle_resp, initXhr, make_driver_method, parseResponse, setupXhrEventHandlers, uuidv4, }; diff --git a/src/puter-js/src/modules/EmailConfirmationDialog.js b/src/puter-js/src/modules/EmailConfirmationDialog.js new file mode 100644 index 000000000..8be9eaa78 --- /dev/null +++ b/src/puter-js/src/modules/EmailConfirmationDialog.js @@ -0,0 +1,207 @@ +class EmailConfirmationDialog extends (globalThis.HTMLElement || Object) { + constructor (message) { + super(); + this.message = message || 'Please confirm your email address to use this service.'; + + this.attachShadow({ mode: 'open' }); + + this.shadowRoot.innerHTML = ` + + + + ✕ + + + + + + Confirm Your Email + ${this.message} + + Close + Go to Puter.com + + + + `; + } + + connectedCallback () { + const dialog = this.shadowRoot.querySelector('dialog'); + + this.shadowRoot.querySelector('.close-btn').addEventListener('click', () => { + this.close(); + }); + + this.shadowRoot.querySelector('#close-btn').addEventListener('click', () => { + this.close(); + }); + + this.shadowRoot.querySelector('#confirm-email-btn').addEventListener('click', () => { + window.open('https://puter.com', '_blank'); + this.close(); + }); + + // Close on backdrop click + dialog.addEventListener('click', (e) => { + if ( e.target === dialog ) { + this.close(); + } + }); + } + + open () { + this.shadowRoot.querySelector('dialog').showModal(); + } + + close () { + this.shadowRoot.querySelector('dialog').close(); + this.remove(); + } +} + +// Only define custom element in environments with DOM support +if ( typeof globalThis.HTMLElement !== 'undefined' && globalThis.customElements ) { + if ( ! customElements.get('email-confirmation-dialog') ) { + customElements.define('email-confirmation-dialog', EmailConfirmationDialog); + } +} + +/** + * Shows an email confirmation dialog to the user. + * Call only when puter.env === 'web' (caller's responsibility). + * @param {string} message - The message to display + */ +export function showEmailConfirmationDialog (message) { + // Only show in browser environments + if ( typeof globalThis.document === 'undefined' ) { + return; + } + + // Check if dialog is already shown to prevent duplicates + if ( document.querySelector('email-confirmation-dialog') ) { + return; + } + + const dialog = new EmailConfirmationDialog(message); + document.body.appendChild(dialog); + dialog.open(); +} + +export default EmailConfirmationDialog;
${this.message}