import React, { useState, useEffect, useCallback } from 'react';
import {
StyleSheet, View, Text, ActivityIndicator, ScrollView, RefreshControl,
} from 'react-native';
import { useFocusEffect } from '@react-navigation/native';
import { useTheme } from '../services/ThemeContext';
import DatabaseService from '../services/DatabaseService';
import GoogleAUTH from '../AUTH/GoogleAUTH';
import NASAUTH from '../AUTH/NASAUTH';
import TopBar from '../components/TopBar';
import PhotoGrid from '../components/PhotoGrid';
import MediaViewer from '../components/MediaViewer';
import { TouchableOpacity } from 'react-native';
const HomeScreen = ({ navigation, route }) => {
const userId = route?.params?.userId;
const { theme } = useTheme();
const [currentUser, setCurrentUser] = useState(null);
const [linkedAccounts, setLinkedAccounts] = useState([]);
const [allMedia, setAllMedia] = useState([]);
const [filteredMedia, setFilteredMedia] = useState([]);
const [selectedFilter, setSelectedFilter] = useState('all');
const [loading, setLoading] = useState(true);
const [refreshing, setRefreshing] = useState(false);
const [selectedMedia, setSelectedMedia] = useState(null);
const [viewerVisible, setViewerVisible] = useState(false);
useFocusEffect(
useCallback(() => {
if (userId) loadUserData();
}, [userId])
);
useEffect(() => {
if (currentUser) loadAllMedia();
}, [currentUser]);
useEffect(() => { filterMedia(); }, [selectedFilter, allMedia]);
const loadUserData = async () => {
try {
const user = await DatabaseService.getUserById(userId);
setCurrentUser(user);
const accounts = await DatabaseService.getLinkedAccounts(userId);
setLinkedAccounts(accounts);
} catch (err) {
console.error('Error loading user data:', err);
}
};
const loadAllMedia = async () => {
if (!loading) setLoading(true);
try {
const mediaFromDb = await DatabaseService.getMediaByUser(userId);
const newMedia = [];
// Google Photos fetch
const googleAccount = linkedAccounts.find((a) => a.service_type === 'GOOGLE_PHOTOS');
if (googleAccount) {
try {
const googleAuth = new GoogleAUTH();
googleAuth.accessToken = googleAccount.account_data?.accessToken;
googleAuth.refreshToken = googleAccount.account_data?.refreshToken;
googleAuth.expiresAt = Date.now() + 3600000;
const photos = await googleAuth.getPhotos(50);
if (photos?.mediaItems?.length) newMedia.push(...photos.mediaItems);
} catch (err) {
console.error('Google Photos fetch error:', err);
}
}
// iCloud fetch (placeholder)
const iosAccount = linkedAccounts.find((a) => a.service_type === 'ICLOUD_PHOTOS');
if (iosAccount) {
try {
console.log('iCloud: placeholder - would fetch photos here');
} catch (err) {
console.error('iCloud fetch error:', err);
}
}
// NAS fetch
const nasAccount = linkedAccounts.find((a) => a.service_type === 'NAS');
if (nasAccount) {
try {
const nasAuth = new NASAUTH();
const nasData = nasAccount.account_data;
await nasAuth.authenticate(nasData.host, nasData.port, nasData.username, nasData.password, nasData.photoFolder);
const nasPhotos = await nasAuth.getPhotos(nasData.photoFolder);
if (nasPhotos?.mediaItems) newMedia.push(...nasPhotos.mediaItems);
await nasAuth.revokeAccess();
} catch (err) {
console.error('NAS fetch error:', err);
}
}
const combined = [...mediaFromDb, ...newMedia];
const unique = Array.from(new Map(combined.map((m) => [m.source_id || m.id || m.path, m])).values());
setAllMedia(unique);
} catch (err) {
console.error('Error loading media:', err);
} finally {
setLoading(false);
setRefreshing(false);
}
};
const filterMedia = () => {
let filtered = allMedia;
if (selectedFilter !== 'all') {
filtered = allMedia.filter((m) => m.source_service === selectedFilter);
}
filtered.sort((a, b) => new Date(b.created_date || 0) - new Date(a.created_date || 0));
setFilteredMedia(filtered);
};
const getServiceIcon = (type) => ({ GOOGLE_PHOTOS: '📷', ICLOUD_PHOTOS: '🍎', NAS: '💾' }[type] || '📱');
const getServiceName = (type) => ({ GOOGLE_PHOTOS: 'Google Photos', ICLOUD_PHOTOS: 'iCloud', NAS: 'NAS' }[type] || type);
if (loading && allMedia.length === 0) {
return (
Loading photos...
);
}
const FilterChips = () => (
setSelectedFilter('all')}
>
All
{linkedAccounts.map((acc) => (
setSelectedFilter(acc.service_type)}
>
{getServiceIcon(acc.service_type)}
{getServiceName(acc.service_type)}
))}
);
return (
navigation.navigate('Search')}
onProfilePress={() => navigation.navigate('Settings', { userId })}
onMenuPress={() => navigation.navigate('Settings', { userId })}
/>
{linkedAccounts.length > 0 && }
{filteredMedia.length === 0 ? (
📸
No Photos Yet
Photos from your connected services will appear here
{ setRefreshing(true); loadAllMedia(); }}
>
Refresh
) : (
{ setSelectedMedia(item); setViewerVisible(true); }}
refreshControl={
{ setRefreshing(true); loadAllMedia(); }} />
}
/>
)}
setViewerVisible(false)}
/>
);
};
const styles = StyleSheet.create({
container: { flex: 1 },
centerContainer: { flex: 1, justifyContent: 'center', alignItems: 'center', paddingHorizontal: 24 },
loadingText: { marginTop: 12, fontSize: 14 },
// Filter chips
filterRow: { paddingHorizontal: 12, paddingVertical: 8, gap: 8 },
chip: {
flexDirection: 'row', alignItems: 'center', paddingHorizontal: 14, paddingVertical: 7,
borderRadius: 20, gap: 6,
},
chipIcon: { fontSize: 13 },
chipText: { fontSize: 13, fontWeight: '500', color: '#3c4043' },
// Empty
emptyTitle: { fontSize: 18, fontWeight: '600', marginBottom: 6 },
emptyText: { fontSize: 13, textAlign: 'center', marginBottom: 20 },
retryButton: { paddingHorizontal: 24, paddingVertical: 10, borderRadius: 20 },
retryButtonText: { color: '#fff', fontSize: 14, fontWeight: '600' },
});
export default HomeScreen;