import 'package:supabase_flutter/supabase_flutter.dart'; class UserInfo { final String? userId; final String? email; final String? username; final String? avatarUrl; UserInfo({this.userId, this.email, this.username, this.avatarUrl}); } class ProfileService { final _supabase = Supabase.instance.client; // Cache to store profile data final Map _usernameCache = {}; final Map _emailCache = {}; final Map _avatarUrlCache = {}; String? _currentUserEmail; String? _currentUsername; String? _currentAvatarUrl; Future initialize() async { await _loadCurrentUserProfile(); } void dispose() { // No resources to clean up } Future _loadCurrentUserProfile() async { final userId = _supabase.auth.currentUser?.id; _currentUserEmail = _supabase.auth.currentUser?.email; if (userId == null) return; // Store current user email in cache if (_currentUserEmail != null) { _emailCache[userId] = _currentUserEmail!; } // Try to get profile data try { final profile = await _supabase .from('profiles') .select('username, avatar_url') .eq('user_id', userId) .single(); if (profile != null) { if (profile['username'] != null && profile['username'].toString().isNotEmpty) { _currentUsername = profile['username'] as String; _usernameCache[userId] = _currentUsername!; } if (profile['avatar_url'] != null && profile['avatar_url'].toString().isNotEmpty) { _currentAvatarUrl = profile['avatar_url'] as String; _avatarUrlCache[userId] = _currentAvatarUrl!; } } } catch (e) { print("[ERROR] Failed to get current user profile: $e"); } // Use email as fallback username if (_currentUsername == null && _currentUserEmail != null) { _currentUsername = _currentUserEmail!.split('@')[0]; } } Future getCurrentUser() async { final userId = _supabase.auth.currentUser?.id; if (_currentUsername == null || _currentAvatarUrl == null) { await _loadCurrentUserProfile(); } return UserInfo( userId: userId, email: _currentUserEmail, username: _currentUsername, avatarUrl: _currentAvatarUrl, ); } Future getUserProfile(String userId) async { // Check if we have this user in cache final email = _emailCache[userId]; final username = _usernameCache[userId]; final avatarUrl = _avatarUrlCache[userId]; // If we have all the data, return from cache if (username != null && avatarUrl != null) { return UserInfo( userId: userId, email: email, username: username, avatarUrl: avatarUrl, ); } // Otherwise fetch from database try { final profile = await _supabase .from('profiles') .select('username, avatar_url') .eq('user_id', userId) .maybeSingle(); if (profile != null) { final fetchedUsername = profile['username'] as String?; final fetchedAvatarUrl = profile['avatar_url'] as String?; // Update cache if (fetchedUsername != null && fetchedUsername.isNotEmpty) { _usernameCache[userId] = fetchedUsername; } if (fetchedAvatarUrl != null && fetchedAvatarUrl.isNotEmpty) { _avatarUrlCache[userId] = fetchedAvatarUrl; } return UserInfo( userId: userId, email: email, username: fetchedUsername ?? (email != null ? email.split('@')[0] : null), avatarUrl: fetchedAvatarUrl, ); } } catch (e) { print("[ERROR] Failed to fetch user profile: $e"); } // Return what we have if fetch failed return UserInfo( userId: userId, email: email, username: username ?? (email != null ? email.split('@')[0] : null), avatarUrl: avatarUrl, ); } }