diff --git a/app/protected/messages/page.tsx b/app/protected/messages/page.tsx
index eaf4c8b8..8e4ee619 100644
--- a/app/protected/messages/page.tsx
+++ b/app/protected/messages/page.tsx
@@ -103,12 +103,14 @@ export default function MessagesPage() {
{conversationName}
- {!selectedConversation.is_group && selectedConversation.other_user && (
+ {!selectedConversation.is_group && selectedConversation.other_user && selectedConversation.other_user.id ? (
+ ) : !selectedConversation.is_group && (
+ No user data
)}
diff --git a/components/messages/ConversationList.tsx b/components/messages/ConversationList.tsx
index 9b0b1669..67fe22c1 100644
--- a/components/messages/ConversationList.tsx
+++ b/components/messages/ConversationList.tsx
@@ -18,6 +18,20 @@ interface ConversationListProps {
}
export function ConversationList({ conversations, selectedId, onSelect, loading }: ConversationListProps) {
+ // Debug: Log conversations data (must be before any returns)
+ React.useEffect(() => {
+ if (!loading && conversations.length > 0) {
+ console.log('ConversationList conversations:', conversations.map(c => ({
+ id: c.id,
+ is_group: c.is_group,
+ other_user: c.other_user ? {
+ id: c.other_user.id,
+ username: c.other_user.username
+ } : null
+ })))
+ }
+ }, [conversations, loading])
+
if (loading) {
return (
@@ -85,11 +99,14 @@ export function ConversationList({ conversations, selectedId, onSelect, loading
{initials}
- {!conversation.is_group && otherUser && (
+ {!conversation.is_group && otherUser && otherUser.id && (
)}
+ {!conversation.is_group && !otherUser && (
+
+ )}
diff --git a/components/messages/UserStatusIndicator.tsx b/components/messages/UserStatusIndicator.tsx
index 3549b21c..6177e6dc 100644
--- a/components/messages/UserStatusIndicator.tsx
+++ b/components/messages/UserStatusIndicator.tsx
@@ -17,7 +17,26 @@ export function UserStatusIndicator({
}: UserStatusIndicatorProps) {
const { presence, loading } = useUserPresence(userId)
- if (loading || !presence) return null
+ // Debug logging
+ React.useEffect(() => {
+ if (presence) {
+ console.log('UserStatusIndicator for', userId, ':', {
+ isOnline: presence.isOnline,
+ lastSeen: presence.lastSeen,
+ loading
+ })
+ }
+ }, [presence, userId, loading])
+
+ if (loading) {
+ console.log('UserStatusIndicator loading for', userId)
+ return null
+ }
+
+ if (!presence) {
+ console.log('UserStatusIndicator no presence data for', userId)
+ return null
+ }
const sizeClasses = {
sm: 'w-2 h-2',
diff --git a/hooks/useUserPresence.ts b/hooks/useUserPresence.ts
index 52a170d1..4a853a6e 100644
--- a/hooks/useUserPresence.ts
+++ b/hooks/useUserPresence.ts
@@ -26,19 +26,35 @@ export function useUserPresence(userId: string | null) {
.from('user_presence')
.select('*')
.eq('user_id', userId)
- .single()
+ .maybeSingle() // Use maybeSingle instead of single to handle no results
+
+ if (error) {
+ console.error('Error fetching presence:', error)
+ }
if (data) {
+ console.log('Fetched presence for user:', userId, data)
setPresence({
userId: data.user_id,
isOnline: data.is_online,
lastSeen: data.last_seen
})
+ } else {
+ // No presence record yet - user is offline
+ console.log('No presence record for user:', userId)
+ setPresence({
+ userId: userId,
+ isOnline: false,
+ lastSeen: null
+ })
}
setLoading(false)
}
fetchPresence()
+
+ // Refresh presence every 10 seconds to catch updates
+ const refreshInterval = setInterval(fetchPresence, 10000)
// Subscribe to presence changes
const subscription = supabase
@@ -52,9 +68,15 @@ export function useUserPresence(userId: string | null) {
filter: `user_id=eq.${userId}`
},
(payload) => {
+ console.log('🔔 Presence update received for', userId, payload)
// eslint-disable-next-line @typescript-eslint/no-explicit-any
const newData = payload.new as any
if (newData) {
+ console.log('📡 Updating presence state:', {
+ userId: newData.user_id,
+ isOnline: newData.is_online,
+ lastSeen: newData.last_seen
+ })
setPresence({
userId: newData.user_id,
isOnline: newData.is_online,
@@ -63,10 +85,13 @@ export function useUserPresence(userId: string | null) {
}
}
)
- .subscribe()
+ .subscribe((status) => {
+ console.log('Subscription status for', userId, ':', status)
+ })
return () => {
subscription.unsubscribe()
+ clearInterval(refreshInterval)
}
}, [userId])
@@ -85,37 +110,65 @@ export function useMyPresence() {
// Set user as online
const setOnline = async () => {
- await supabase
+ const { error } = await supabase
.from('user_presence')
- .upsert({
- user_id: user.id,
- is_online: true,
- last_seen: new Date().toISOString()
- })
+ .upsert(
+ {
+ user_id: user.id,
+ is_online: true,
+ last_seen: new Date().toISOString(),
+ updated_at: new Date().toISOString()
+ },
+ {
+ onConflict: 'user_id'
+ }
+ )
+
+ if (error) {
+ console.error('Error setting online:', error)
+ } else {
+ console.log('✅ Set user online:', user.id)
+ }
}
// Set user as offline
const setOffline = async () => {
- await supabase
+ const { error } = await supabase
.from('user_presence')
- .upsert({
- user_id: user.id,
- is_online: false,
- last_seen: new Date().toISOString()
- })
+ .upsert(
+ {
+ user_id: user.id,
+ is_online: false,
+ last_seen: new Date().toISOString(),
+ updated_at: new Date().toISOString()
+ },
+ {
+ onConflict: 'user_id'
+ }
+ )
+
+ if (error) {
+ console.error('Error setting offline:', error)
+ } else {
+ console.log('❌ Set user offline:', user.id)
+ }
}
// Update presence every 30 seconds
+ // More frequent updates ensure status is current
const updatePresence = async () => {
if (document.visibilityState === 'visible') {
await setOnline()
}
}
- // Set online on mount
+ // Set online immediately on mount
setOnline()
+
+ // Also set online after a short delay to ensure it's registered
+ setTimeout(setOnline, 1000)
- // Update presence periodically
+ // Update presence periodically (every 30 seconds)
const interval = setInterval(updatePresence, 30000)
// Handle visibility change