|
|
<!DOCTYPE html> |
|
|
<html lang="en"> |
|
|
<head> |
|
|
<meta charset="UTF-8" /> |
|
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" /> |
|
|
<title>Everyday Cats – Sign-in</title> |
|
|
<style> |
|
|
body { |
|
|
background: #fffafc; |
|
|
color: #222; |
|
|
font-family: "Inter", system-ui, sans-serif; |
|
|
display: flex; |
|
|
align-items: center; |
|
|
justify-content: center; |
|
|
height: 100vh; |
|
|
flex-direction: column; |
|
|
text-align: center; |
|
|
margin: 0; |
|
|
} |
|
|
.container { |
|
|
max-width: 400px; |
|
|
padding: 2rem; |
|
|
} |
|
|
h1 { |
|
|
font-size: 1.8rem; |
|
|
margin-bottom: 0.5rem; |
|
|
} |
|
|
p { |
|
|
font-size: 1rem; |
|
|
opacity: 0.8; |
|
|
margin-bottom: 1.5rem; |
|
|
} |
|
|
button { |
|
|
background: #FFB84D; |
|
|
border: none; |
|
|
padding: 0.75rem 1.5rem; |
|
|
border-radius: 9999px; |
|
|
font-size: 1rem; |
|
|
font-weight: 600; |
|
|
color: white; |
|
|
cursor: pointer; |
|
|
transition: 0.2s; |
|
|
width: 100%; |
|
|
max-width: 280px; |
|
|
} |
|
|
button:hover { |
|
|
background: #ffa833; |
|
|
} |
|
|
button:disabled { |
|
|
opacity: 0.6; |
|
|
cursor: not-allowed; |
|
|
} |
|
|
.error { |
|
|
color: #d32f2f; |
|
|
margin-top: 1rem; |
|
|
font-size: 0.9rem; |
|
|
word-break: break-word; |
|
|
} |
|
|
.loading { |
|
|
margin-top: 1rem; |
|
|
opacity: 0.7; |
|
|
} |
|
|
.note { |
|
|
margin-top: 12px; |
|
|
font-size: 0.85rem; |
|
|
opacity: 0.85; |
|
|
} |
|
|
</style> |
|
|
</head> |
|
|
<body> |
|
|
<div class="container"> |
|
|
<h1 id="title">Welcome to Everyday Cats</h1> |
|
|
<p id="message">Sign in with your Google account to continue</p> |
|
|
<button id="authButton" onclick="handleAuth()">Sign in with Google</button> |
|
|
<p class="loading" id="loading" style="display: none;">Processing...</p> |
|
|
<p class="error" id="error"></p> |
|
|
<p class="note" id="note">Tip: Serve this page over http(s). Add your test domain to Firebase Auth → Authorized domains.</p> |
|
|
</div> |
|
|
|
|
|
|
|
|
<script type="module"> |
|
|
import { initializeApp } from 'https://www.gstatic.com/firebasejs/10.7.1/firebase-app.js'; |
|
|
import { |
|
|
getAuth, |
|
|
signInWithPopup, |
|
|
signInWithRedirect, |
|
|
getRedirectResult, |
|
|
GoogleAuthProvider, |
|
|
onAuthStateChanged |
|
|
} from 'https://www.gstatic.com/firebasejs/10.7.1/firebase-auth.js'; |
|
|
|
|
|
|
|
|
const firebaseConfig = { |
|
|
apiKey: "AIzaSyAJZ5UwyLo4b4L8_G7Nocw0nj7dhyBZ_yU", |
|
|
authDomain: "cartpost-db-06.firebaseapp.com", |
|
|
projectId: "cartpost-db-06", |
|
|
storageBucket: "cartpost-db-06.firebasestorage.app", |
|
|
messagingSenderId: "212802992706", |
|
|
appId: "1:212802992706:web:2a32a453c42cbc3bdfcbdb", |
|
|
measurementId: "G-JYWF6B9MVZ" |
|
|
}; |
|
|
|
|
|
|
|
|
const app = initializeApp(firebaseConfig); |
|
|
const auth = getAuth(app); |
|
|
const provider = new GoogleAuthProvider(); |
|
|
|
|
|
|
|
|
const appScheme = "everydaydresscode"; |
|
|
|
|
|
|
|
|
const titleEl = document.getElementById('title'); |
|
|
const messageEl = document.getElementById('message'); |
|
|
const buttonEl = document.getElementById('authButton'); |
|
|
const loadingEl = document.getElementById('loading'); |
|
|
const errorEl = document.getElementById('error'); |
|
|
|
|
|
|
|
|
function isLikelyWebViewOrInApp() { |
|
|
const ua = navigator.userAgent || ''; |
|
|
|
|
|
const webviewMarkers = /wv|WebView|FBAN|FBAV|Instagram|KAKAOTALK|Line|MicroMessenger/i; |
|
|
|
|
|
return webviewMarkers.test(ua) || (/Android/i.test(ua) && !/Chrome/i.test(ua)); |
|
|
} |
|
|
|
|
|
function resetUI() { |
|
|
buttonEl.disabled = false; |
|
|
loadingEl.style.display = 'none'; |
|
|
} |
|
|
|
|
|
function safeSetError(msg) { |
|
|
|
|
|
errorEl.textContent = String(msg || 'Authentication failed.'); |
|
|
} |
|
|
|
|
|
|
|
|
getRedirectResult(auth) |
|
|
.then(async (result) => { |
|
|
alert("rere", result); |
|
|
if (result && result.user) { |
|
|
|
|
|
const user = result.user; |
|
|
try { |
|
|
const token = await user.getIdToken(); |
|
|
showSuccess(user); |
|
|
|
|
|
setTimeout(() => redirectToApp(token, user), 1000); |
|
|
} catch (tokenErr) { |
|
|
console.error('Token error after redirect:', tokenErr); |
|
|
safeSetError('Signed in but failed to retrieve token. See console for details.'); |
|
|
} |
|
|
} |
|
|
}) |
|
|
.catch((err) => { |
|
|
console.error('getRedirectResult error:', err.code, err.message); |
|
|
|
|
|
safeSetError('Authentication after redirect failed. See console for details.'); |
|
|
resetUI(); |
|
|
}); |
|
|
|
|
|
|
|
|
onAuthStateChanged(auth, (user) => { |
|
|
if (user) { |
|
|
|
|
|
showSuccess(user); |
|
|
} |
|
|
}); |
|
|
|
|
|
|
|
|
window.handleAuth = async function() { |
|
|
|
|
|
buttonEl.disabled = true; |
|
|
loadingEl.style.display = 'block'; |
|
|
errorEl.textContent = ''; |
|
|
|
|
|
try { |
|
|
|
|
|
|
|
|
if (true) { |
|
|
|
|
|
console.log('Detected webview/in-app: using signInWithRedirect.'); |
|
|
|
|
|
const result = await signInWithRedirect(auth, provider) |
|
|
|
|
|
|
|
|
alert("rere", result); |
|
|
if (result && result.user) { |
|
|
|
|
|
const user = result.user; |
|
|
try { |
|
|
const token = await user.getIdToken(); |
|
|
showSuccess(user); |
|
|
|
|
|
setTimeout(() => redirectToApp(token, user), 1000); |
|
|
} catch (tokenErr) { |
|
|
console.error('Token error after redirect:', tokenErr); |
|
|
safeSetError('Signed in but failed to retrieve token. See console for details.'); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
} else { |
|
|
|
|
|
console.log('Using signInWithPopup for desktop browser.'); |
|
|
const result = await signInWithPopup(auth, provider); |
|
|
|
|
|
|
|
|
if (result && result.user) { |
|
|
const user = result.user; |
|
|
const token = await user.getIdToken(); |
|
|
showSuccess(user); |
|
|
|
|
|
setTimeout(() => redirectToApp(token, user), 800); |
|
|
} else { |
|
|
|
|
|
console.warn('signInWithPopup returned no user:', result); |
|
|
safeSetError('Sign-in did not complete. Check console for details.'); |
|
|
resetUI(); |
|
|
} |
|
|
} |
|
|
} catch (err) { |
|
|
|
|
|
console.error('Auth error:', err.code, err.message, err); |
|
|
alert('Auth error:', err.code, err.message, err); |
|
|
let msg = 'Authentication failed. See console for details.'; |
|
|
if (err && err.code === 'auth/popup-closed-by-user') msg = 'Sign-in cancelled. Please try again.'; |
|
|
else if (err && err.code === 'auth/popup-blocked') msg = 'Pop-up blocked. Allow pop-ups and try again.'; |
|
|
else if (err && err.code === 'auth/cancelled-popup-request') msg = 'Popup request cancelled (race). Try again.'; |
|
|
else if (err && err.code === 'auth/unauthorized-domain') msg = 'Unauthorized domain — add this domain in Firebase Console (Auth → Authorized domains).'; |
|
|
safeSetError(msg); |
|
|
resetUI(); |
|
|
} |
|
|
}; |
|
|
|
|
|
|
|
|
function showSuccess(user) { |
|
|
titleEl.textContent = 'Sign-in Complete'; |
|
|
messageEl.innerHTML = `Welcome, <strong>${user.displayName || user.email}</strong>! Redirecting to app...`; |
|
|
buttonEl.textContent = 'Open App'; |
|
|
buttonEl.onclick = async () => { |
|
|
|
|
|
const current = auth.currentUser; |
|
|
if (!current) { |
|
|
safeSetError('No signed-in user available. Reload and try again.'); |
|
|
return; |
|
|
} |
|
|
try { |
|
|
const token = await current.getIdToken(); |
|
|
redirectToApp(token, current); |
|
|
} catch (e) { |
|
|
console.error('Failed to get token on manual Open App:', e); |
|
|
safeSetError('Failed to get token. See console.'); |
|
|
} |
|
|
}; |
|
|
buttonEl.disabled = false; |
|
|
loadingEl.style.display = 'none'; |
|
|
} |
|
|
|
|
|
async function redirectToApp(token, user) { |
|
|
if (!user) { |
|
|
safeSetError('No signed-in user available to redirect.'); |
|
|
return; |
|
|
} |
|
|
|
|
|
if (!token) { |
|
|
try { |
|
|
token = await user.getIdToken(); |
|
|
} catch (e) { |
|
|
console.error('Failed to fetch token before redirect:', e); |
|
|
safeSetError('Failed to fetch token. See console.'); |
|
|
return; |
|
|
} |
|
|
} |
|
|
|
|
|
const userData = { |
|
|
uid: user.uid, |
|
|
email: user.email, |
|
|
displayName: user.displayName, |
|
|
photoURL: user.photoURL, |
|
|
token |
|
|
}; |
|
|
|
|
|
const encodedData = encodeURIComponent(JSON.stringify(userData)); |
|
|
|
|
|
window.location.href = `${appScheme}://auth?data=${encodedData}`; |
|
|
|
|
|
|
|
|
setTimeout(() => { |
|
|
messageEl.innerHTML = 'If the app didn\'t open automatically, please open it manually.'; |
|
|
}, 2000); |
|
|
} |
|
|
|
|
|
|
|
|
</script> |
|
|
</body> |
|
|
</html> |