login for RN app

This commit is contained in:
seb
2026-07-19 23:42:17 +02:00
parent af9e072427
commit c5b2f06919
7 changed files with 199 additions and 29 deletions

View File

@@ -2,6 +2,32 @@ const GIS_SCRIPT = 'https://accounts.google.com/gsi/client';
let scriptPromise;
/** WebView consoles print objects as [object Object]; always log a string. */
export function logError(tag, details) {
let text;
try {
text = JSON.stringify(details, errorReplacer, 2);
} catch {
text = String(details);
}
console.error(`${tag} ${text}`);
}
function errorReplacer(_key, value) {
if (value instanceof Error) {
return {
name: value.name,
message: value.message,
code: value.code,
status: value.status,
stack: value.stack,
cause: value.cause,
...Object.fromEntries(Object.entries(value)),
};
}
return value;
}
function loadGoogleScript() {
if (window.google?.accounts?.id) return Promise.resolve();
if (scriptPromise) return scriptPromise;
@@ -12,7 +38,21 @@ function loadGoogleScript() {
script.async = true;
script.defer = true;
script.onload = () => resolve();
script.onerror = () => reject(new Error('Failed to load Google Sign-In'));
script.onerror = () => {
scriptPromise = null;
// <script onerror> does not expose a message; fetch to get a real Error.
fetch(GIS_SCRIPT).then(
(res) =>
reject(
new Error(
res.ok
? `Failed to execute ${GIS_SCRIPT}`
: `Failed to load ${GIS_SCRIPT}: HTTP ${res.status} ${res.statusText}`,
),
),
reject,
);
};
document.head.appendChild(script);
});
@@ -76,6 +116,7 @@ function clickRenderedGoogleButton(clientId, onCredential) {
/**
* Prompt for a Google ID token (One Tap, falling back to the sign-in popup).
* In Dash Native (`window.__dashHost`), uses the host bridge with the same web OAuth client ID.
* @param {string} clientId
* @param {{ onFedcmBlocked?: () => void }} [options]
*/
@@ -84,6 +125,24 @@ export async function requestGoogleIdToken(clientId, { onFedcmBlocked } = {}) {
throw new Error('Google client ID is not configured');
}
const host = window.__dashHost;
if (
host?.isDashNative === true &&
host.googleSignIn === true &&
typeof host.requestGoogleIdToken === 'function'
) {
try {
return await host.requestGoogleIdToken(clientId);
} catch (err) {
logError('[googleSignIn] native host requestGoogleIdToken failed', {
clientId,
origin: window.location.origin,
error: err,
});
throw err;
}
}
await loadGoogleScript();
return new Promise((resolve, reject) => {