fix: AI chat authentication on iOS Safari by using global auth state
Problem: - Floating chat had its own separate authentication check using localStorage - iOS Safari has restrictions on localStorage access, especially with tracking prevention - This caused logged-in users to still see login prompt in AI chat Solution: - Replace local auth state management with global useAuth hook from AuthProvider - Remove redundant checkAuthStatus() function - Update all authentication checks to use isAuthenticated from useAuth - Update token retrieval to get directly from localStorage only when needed Benefits: - Single source of truth for authentication across the app - More reliable authentication state management - Better compatibility with iOS Safari's privacy features - Automatic auth state synchronization when user logs in/out Changes: - Use useAuth hook instead of local isAuthenticated/authToken state - Remove checkAuthStatus() function - Update loadConversations to read token from localStorage directly - Update loadConversation to read token from localStorage directly - Update handleSendMessage to read token from localStorage directly - Simplify handleAuthSuccess to rely on global auth state updates 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -46,6 +46,7 @@ import { useState, useRef, useEffect, useCallback } from 'react'
|
||||
import { useTranslations, useLocale } from 'next-intl'
|
||||
import ReactMarkdown from 'react-markdown'
|
||||
import { AuthModal } from '@/components/auth/auth-modal'
|
||||
import { useAuth } from '@/hooks/use-auth'
|
||||
|
||||
// Random Bible-related loading messages
|
||||
const LOADING_MESSAGES = [
|
||||
@@ -77,6 +78,7 @@ export default function FloatingChat() {
|
||||
const theme = useTheme()
|
||||
const t = useTranslations('chat')
|
||||
const locale = useLocale()
|
||||
const { user, isAuthenticated } = useAuth() // Use global auth state
|
||||
const [isOpen, setIsOpen] = useState(false)
|
||||
const [isMinimized, setIsMinimized] = useState(false)
|
||||
const [isFullscreen, setIsFullscreen] = useState(false)
|
||||
@@ -98,8 +100,6 @@ export default function FloatingChat() {
|
||||
// Conversation management state
|
||||
const [conversations, setConversations] = useState<Conversation[]>([])
|
||||
const [activeConversationId, setActiveConversationId] = useState<string | null>(null)
|
||||
const [isAuthenticated, setIsAuthenticated] = useState(false)
|
||||
const [authToken, setAuthToken] = useState<string | null>(null)
|
||||
const [isLoadingConversations, setIsLoadingConversations] = useState(false)
|
||||
const [menuAnchorEl, setMenuAnchorEl] = useState<HTMLElement | null>(null)
|
||||
const [selectedConversationId, setSelectedConversationId] = useState<string | null>(null)
|
||||
@@ -144,56 +144,22 @@ export default function FloatingChat() {
|
||||
return () => window.removeEventListener('auth:sign-in-required', handler as EventListener)
|
||||
}, [])
|
||||
|
||||
// Check authentication status
|
||||
useEffect(() => {
|
||||
checkAuthStatus()
|
||||
}, [])
|
||||
|
||||
// Load conversations when authenticated
|
||||
useEffect(() => {
|
||||
if (isAuthenticated && authToken) {
|
||||
if (isAuthenticated) {
|
||||
loadConversations()
|
||||
}
|
||||
}, [isAuthenticated, authToken, locale])
|
||||
|
||||
const checkAuthStatus = useCallback(async () => {
|
||||
try {
|
||||
const token = localStorage.getItem('authToken')
|
||||
if (token) {
|
||||
// Verify token with the server
|
||||
const response = await fetch('/api/auth/me', {
|
||||
headers: {
|
||||
'Authorization': `Bearer ${token}`
|
||||
}
|
||||
})
|
||||
|
||||
if (response.ok) {
|
||||
setAuthToken(token)
|
||||
setIsAuthenticated(true)
|
||||
} else {
|
||||
localStorage.removeItem('authToken')
|
||||
setIsAuthenticated(false)
|
||||
setAuthToken(null)
|
||||
}
|
||||
} else {
|
||||
setIsAuthenticated(false)
|
||||
setAuthToken(null)
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Chat - Auth check failed:', error)
|
||||
setIsAuthenticated(false)
|
||||
setAuthToken(null)
|
||||
}
|
||||
}, [])
|
||||
}, [isAuthenticated, locale])
|
||||
|
||||
const loadConversations = useCallback(async () => {
|
||||
if (!authToken) return
|
||||
const token = localStorage.getItem('authToken')
|
||||
if (!token) return
|
||||
|
||||
setIsLoadingConversations(true)
|
||||
try {
|
||||
const response = await fetch(`/api/chat/conversations?language=${locale}&limit=20`, {
|
||||
headers: {
|
||||
'Authorization': `Bearer ${authToken}`
|
||||
'Authorization': `Bearer ${token}`
|
||||
}
|
||||
})
|
||||
|
||||
@@ -208,15 +174,16 @@ export default function FloatingChat() {
|
||||
} finally {
|
||||
setIsLoadingConversations(false)
|
||||
}
|
||||
}, [authToken, locale])
|
||||
}, [locale])
|
||||
|
||||
const loadConversation = useCallback(async (conversationId: string) => {
|
||||
if (!authToken) return
|
||||
const token = localStorage.getItem('authToken')
|
||||
if (!token) return
|
||||
|
||||
try {
|
||||
const response = await fetch(`/api/chat/conversations/${conversationId}`, {
|
||||
headers: {
|
||||
'Authorization': `Bearer ${authToken}`
|
||||
'Authorization': `Bearer ${token}`
|
||||
}
|
||||
})
|
||||
|
||||
@@ -239,7 +206,7 @@ export default function FloatingChat() {
|
||||
} catch (error) {
|
||||
console.error('Error loading conversation:', error)
|
||||
}
|
||||
}, [authToken])
|
||||
}, [])
|
||||
|
||||
const createNewConversation = useCallback(() => {
|
||||
// Reset to a new conversation
|
||||
@@ -369,12 +336,9 @@ export default function FloatingChat() {
|
||||
}
|
||||
|
||||
// Add authentication if available
|
||||
console.log('Chat - authToken value:', authToken ? 'present' : 'null')
|
||||
if (authToken) {
|
||||
headers['Authorization'] = `Bearer ${authToken}`
|
||||
console.log('Chat - Authorization header added')
|
||||
} else {
|
||||
console.log('Chat - No authToken, skipping Authorization header')
|
||||
const token = localStorage.getItem('authToken')
|
||||
if (token) {
|
||||
headers['Authorization'] = `Bearer ${token}`
|
||||
}
|
||||
|
||||
const response = await fetch('/api/chat', {
|
||||
@@ -456,8 +420,8 @@ export default function FloatingChat() {
|
||||
|
||||
const handleAuthSuccess = () => {
|
||||
setAuthModalOpen(false)
|
||||
// Re-check auth status to update the UI
|
||||
checkAuthStatus()
|
||||
// Auth state will be updated automatically by the global useAuth hook
|
||||
// Load conversations will trigger automatically via useEffect when isAuthenticated changes
|
||||
}
|
||||
|
||||
return (
|
||||
|
||||
Reference in New Issue
Block a user