import { RefreshControl, StyleSheet, View, ViewToken } from 'react-native'; import { ThemedText } from '@/components/ThemedText'; import { ThemedView } from '@/components/ThemedView'; import { prettyName, useFileSystem } from '@/hooks/useFilesystem'; import { format } from 'date-fns'; import { StorageAccessFramework } from 'expo-file-system'; import { useNavigation } from 'expo-router'; import { useCallback, useState } from 'react'; import { FlatList } from 'react-native-gesture-handler'; import Markdown from 'react-native-markdown-display'; import { ActivityIndicator, FAB, Text, TouchableRipple, useTheme } from 'react-native-paper'; import { SafeAreaView } from 'react-native-safe-area-context'; export default function HomeScreen() { const navigation = useNavigation(); const theme = useTheme(); const styles = StyleSheet.create({ fab: { position: 'absolute', margin: 16, right: 0, bottom: 0, backgroundColor: theme.colors.primary, // Use your theme's primary color }, container: { backgroundColor: theme.colors.primary, position: 'absolute', top: 0, left: 0, right: 0, height: 100, zIndex: 1000, }, safeArea: { flex: 1, marginTop: 100, backgroundColor: theme.colors.surface, // padding: 10 }, entryCard: { backgroundColor: theme.colors.surface, height: 150 , alignItems: 'center', }, }); const { dataDirectoryUri, loadFiles, files, directorySize } = useFileSystem(); const [refreshing, setRefreshing] = useState(false); const [loadedContents, setLoadedContents] = useState>(new Map()); const [lastViewableItems, setLastViewableItems] = useState([]); const onRefresh = async () => { setRefreshing(true); setLoadedContents(new Map()); // Clear cached content await loadFiles(); // Reload content for currently visible items lastViewableItems.forEach(({ item }) => { loadFileContent(item.uri, true); // Force reload }); setRefreshing(false); }; const loadFileContent = async (fileUri: string, forceReload = false) => { if (loadedContents.has(fileUri) && !forceReload) return; // Already loaded try { // Replace with your actual file reading logic const content = await StorageAccessFramework.readAsStringAsync(fileUri); setLoadedContents(prev => new Map(prev).set(fileUri, content)); } catch (error) { console.error('Error loading file content:', error); } }; const onViewableItemsChanged = useCallback(({ viewableItems }: { viewableItems: ViewToken[] }) => { setLastViewableItems(viewableItems); // Track visible items viewableItems.forEach(({ item }) => { loadFileContent(item.uri); }); }, []); const entryPreview = (fileUri: string) => { if (!loadedContents.has(fileUri)) return null; const preview = loadedContents.get(fileUri)?.slice(0, 200); if (!preview) return null; // No content to show const extra = loadedContents.get(fileUri)?.slice(200); if (!extra) return preview; // No extra content to show const extraLength = extra.trim().split(/\s+/).filter(Boolean).length; return preview! + (extra ? ` *[... ${extraLength} words]*` : ''); }; const renderFileItem = ({ item: f }: { item: typeof files[0] }) => ( { navigation.navigate('Editor', { fileUri: f.uri, fileDatetime: f.datetime }, ); }} > {format(f.datetime, "hh:mm aaa")} {loadedContents.has(f.uri) && ( {entryPreview(f.uri) || } )} ); return ( item.uri} onViewableItemsChanged={onViewableItemsChanged} viewabilityConfig={{ itemVisiblePercentThreshold: 50 }} refreshControl={ } ListHeaderComponent={ {prettyName(dataDirectoryUri, { pathContext: 'full' })}: {' '}{files.length} {files.length == 1 ? "entry" : "entries"}, {directorySize} MB } /> { navigation.navigate('Editor' as never); }} /> ); }