safari fix
This commit is contained in:
43
src/App.css
43
src/App.css
@@ -104,7 +104,7 @@
|
|||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
gap: 1.75rem;
|
gap: 1.75rem;
|
||||||
background: var(--color-surface);
|
background: #fff;
|
||||||
border-radius: 24px;
|
border-radius: 24px;
|
||||||
border-top: 4px solid #22c55e;
|
border-top: 4px solid #22c55e;
|
||||||
padding: 2rem 1.75rem;
|
padding: 2rem 1.75rem;
|
||||||
@@ -168,6 +168,29 @@
|
|||||||
text-align: left;
|
text-align: left;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Login page is always light — ignore dark / liquid-glass themes */
|
||||||
|
[data-theme="dark"] .lp,
|
||||||
|
[data-theme="liquid-glass"] .lp {
|
||||||
|
background: linear-gradient(160deg, #eef6ee 0%, #dcfce7 100%);
|
||||||
|
}
|
||||||
|
[data-theme="dark"] .lp__form,
|
||||||
|
[data-theme="liquid-glass"] .lp__form {
|
||||||
|
background: #fff;
|
||||||
|
backdrop-filter: none;
|
||||||
|
-webkit-backdrop-filter: none;
|
||||||
|
border: none;
|
||||||
|
border-top: 4px solid #22c55e;
|
||||||
|
box-shadow: 0 8px 32px rgba(0, 0, 0, 0.08);
|
||||||
|
}
|
||||||
|
[data-theme="dark"] .lp__tagline,
|
||||||
|
[data-theme="liquid-glass"] .lp__tagline {
|
||||||
|
color: #4b505a;
|
||||||
|
}
|
||||||
|
[data-theme="dark"] .lp__privacy,
|
||||||
|
[data-theme="liquid-glass"] .lp__privacy {
|
||||||
|
color: #6d727a;
|
||||||
|
}
|
||||||
|
|
||||||
/* kept for other callers */
|
/* kept for other callers */
|
||||||
.login-card__error {
|
.login-card__error {
|
||||||
margin: 0;
|
margin: 0;
|
||||||
@@ -3215,8 +3238,7 @@
|
|||||||
[data-theme="liquid-glass"] .settings-tutorial-btn,
|
[data-theme="liquid-glass"] .settings-tutorial-btn,
|
||||||
[data-theme="liquid-glass"] .settings-clear-btn,
|
[data-theme="liquid-glass"] .settings-clear-btn,
|
||||||
[data-theme="liquid-glass"] .settings-signout-btn,
|
[data-theme="liquid-glass"] .settings-signout-btn,
|
||||||
[data-theme="liquid-glass"] .bottom-nav,
|
[data-theme="liquid-glass"] .bottom-nav {
|
||||||
[data-theme="liquid-glass"] .lp__form {
|
|
||||||
background: var(--glass-bg);
|
background: var(--glass-bg);
|
||||||
backdrop-filter: var(--glass-blur);
|
backdrop-filter: var(--glass-blur);
|
||||||
-webkit-backdrop-filter: var(--glass-blur);
|
-webkit-backdrop-filter: var(--glass-blur);
|
||||||
@@ -3497,6 +3519,21 @@
|
|||||||
box-shadow: 0 1px 8px rgba(74, 222, 128, 0.1);
|
box-shadow: 0 1px 8px rgba(74, 222, 128, 0.1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Login page is always light — force button to light style */
|
||||||
|
[data-theme="dark"] .lp .google-sign-in-btn,
|
||||||
|
[data-theme="liquid-glass"] .lp .google-sign-in-btn {
|
||||||
|
background: #fff;
|
||||||
|
border-color: #dadce0;
|
||||||
|
color: #3c4043;
|
||||||
|
}
|
||||||
|
|
||||||
|
[data-theme="dark"] .lp .google-sign-in-btn:hover:not(:disabled),
|
||||||
|
[data-theme="liquid-glass"] .lp .google-sign-in-btn:hover:not(:disabled) {
|
||||||
|
background: #f8f9fa;
|
||||||
|
border-color: #dadce0;
|
||||||
|
box-shadow: 0 1px 6px rgba(0, 0, 0, 0.1);
|
||||||
|
}
|
||||||
|
|
||||||
/* ============================
|
/* ============================
|
||||||
WELCOME MODAL
|
WELCOME MODAL
|
||||||
============================ */
|
============================ */
|
||||||
|
|||||||
@@ -191,11 +191,12 @@ export function AuthProvider({ children }: { children: ReactNode }) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
// Handle returning from a redirect sign-in (mobile flow)
|
// Handle returning from a redirect sign-in (Safari / iOS / Android WebViews)
|
||||||
getRedirectResult(auth).catch((error) => {
|
getRedirectResult(auth).catch((error) => {
|
||||||
console.error('[Auth] Redirect sign-in error:', error)
|
console.error('[Auth] Redirect sign-in error:', error)
|
||||||
setAuthError(error instanceof Error ? error.message : 'Sign-in failed')
|
setAuthError(error instanceof Error ? error.message : 'Sign-in failed')
|
||||||
})
|
})
|
||||||
|
// onAuthStateChanged below handles the successful redirect result automatically
|
||||||
|
|
||||||
const unsubscribe = onAuthStateChanged(auth, async (u) => {
|
const unsubscribe = onAuthStateChanged(auth, async (u) => {
|
||||||
setUser(u)
|
setUser(u)
|
||||||
@@ -218,6 +219,14 @@ export function AuthProvider({ children }: { children: ReactNode }) {
|
|||||||
async function signInWithGoogle() {
|
async function signInWithGoogle() {
|
||||||
setAuthError(null)
|
setAuthError(null)
|
||||||
await setPersistence(auth, browserLocalPersistence)
|
await setPersistence(auth, browserLocalPersistence)
|
||||||
|
|
||||||
|
// Safari blocks cross-origin storage in popups (ITP), so use redirect flow
|
||||||
|
const isSafari = /^((?!chrome|android).)*safari/i.test(navigator.userAgent)
|
||||||
|
if (isSafari) {
|
||||||
|
await signInWithRedirect(auth, googleProvider)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
await signInWithPopup(auth, googleProvider)
|
await signInWithPopup(auth, googleProvider)
|
||||||
} catch (err: unknown) {
|
} catch (err: unknown) {
|
||||||
|
|||||||
@@ -40,7 +40,7 @@ export default function LoginPage() {
|
|||||||
// Without the `user` check here, the login form flashes for one frame
|
// Without the `user` check here, the login form flashes for one frame
|
||||||
// between loading→false and the useEffect redirect.
|
// between loading→false and the useEffect redirect.
|
||||||
if (loading || signingIn || user) {
|
if (loading || signingIn || user) {
|
||||||
return <PageLoader />
|
return <div style={{ background: '#eef6ee', height: '100dvh' }}><PageLoader transparent /></div>
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
|||||||
Reference in New Issue
Block a user