import { StatusBar } from 'expo-status-bar'; import React, { useState, useEffect } from 'react'; import { View, ActivityIndicator, StyleSheet, SafeAreaView, FlatList, Alert } from 'react-native'; import { Button, IconButton } from 'react-native-paper'; import API from './../API.js'; import Post from './../components/Post.js'; import NewPost from "./../components/NewPost.js"; import ProfileHeader from '../components/ProfileHeader.js'; import AsyncStorage from '@react-native-async-storage/async-storage'; import { useSnapshot } from 'valtio'; import GlobalState from '../contexts/GlobalState.js'; const PROFILE_LOG_PREFIX = '[Profile]'; const logProfile = (...args) => { if (__DEV__) console.log(PROFILE_LOG_PREFIX, ...args); }; const storeProfilePosts = async (profileid, value) => { try { const jsonValue = JSON.stringify(value) await AsyncStorage.setItem('profile_' + profileid, jsonValue) } catch (e) { } } const getProfilePosts = async (profileid) => { try { const value = await AsyncStorage.getItem('profile_' + profileid) if (value !== null) { return JSON.parse(value); } return []; } catch (e) { console.log('fail getProfilePosts', e) return []; } } let Profile = ({ navigation, route }) => { const viewer = useSnapshot(GlobalState).me || {}; let [Posts, setPosts] = useState([]); let [profile, setProfile] = useState({}); const [showNewPost, setShowNewPost] = useState(false); const [tag, setTag] = useState(''); const [loading, setLoading] = useState(true); const [isDeletingGroup, setIsDeletingGroup] = useState(false); const isOwnedGroup = !!( profile?._id && profile?.isGroup && String(profile?.userid || '') === String(viewer?.userid || '') ); useEffect(() => { let subscribed = true; const getData = async () => { logProfile('load:start', { profileid: route?.params?.profileid || null, tag, }); setLoading(true); setPosts([]); if (route.params && route.params.profileid && tag == '') { logProfile('cache:read:start', { profileid: route.params.profileid }); await API.getUserProfile(route.params.profileid).then((profileObj) => { if(!subscribed) return 0; const nextProfile = profileObj && profileObj._id ? profileObj : {}; const profileData = nextProfile.profile || {}; setProfile(nextProfile); navigation.setOptions({ title: (profileData.firstName || "") + " " + (profileData.lastName || "") }); logProfile('profile:loaded', { profileid: nextProfile._id || route.params.profileid, hasName: !!(profileData.firstName || profileData.lastName), }); }); await getProfilePosts(route.params.profileid).then((cachedPosts) => { const safeCachedPosts = Array.isArray(cachedPosts) ? cachedPosts : []; setPosts(safeCachedPosts); logProfile('cache:read:end', { profileid: route.params.profileid, count: safeCachedPosts.length, }); }); API.getPosts(route.params.profileid).then((data) => { if(!subscribed) return 0; const safePosts = Array.isArray(data) ? data : []; setPosts(safePosts); storeProfilePosts(route.params.profileid, safePosts); setLoading(false); logProfile('network:loaded', { profileid: route.params.profileid, count: safePosts.length, cached: true, }); }); } else { if(route.params && route.params.profileid){ logProfile('tag:load:start', { profileid: route.params.profileid, tag, }); API.getPostsWithTag(route.params.profileid, tag).then((data) => { if(!subscribed) return 0; const safeTagPosts = Array.isArray(data?.posts) ? data.posts : []; setPosts(safeTagPosts); setLoading(false); logProfile('tag:load:end', { profileid: route.params.profileid, tag, count: safeTagPosts.length, }); }); } else { // if no profile information is pressent should load feed logProfile('redirect:feed'); navigation.navigate('Feed') } } logProfile('load:end'); } getData(); return ()=>{ subscribed = false; logProfile('load:cleanup'); } }, [tag, route.params?.profileid]); const getTagPosts = ()=>{ API.getPostsWithTag(tag).then((data) => { //if(!subscribed) return 0; console.log(data.posts); setPosts(Array.isArray(data?.posts) ? data.posts : []); }); } const renderPost = (({ item }) => { if (item.nonOrganicType) return (<>); return (); }); const handleDeleteGroup = () => { if (!profile?._id || isDeletingGroup) return; Alert.alert( "Delete group?", "This will permanently delete this group profile.", [ { text: "Cancel", style: "cancel" }, { text: "Delete", style: "destructive", onPress: async () => { setIsDeletingGroup(true); try { const result = await API.deleteProfile(profile._id); if (result?.status !== "ok") { return Alert.alert("Could not delete group", result?.status || "Please try again."); } const me = await API.getMe(); if (me && me._id) GlobalState.me = me; if (navigation.canGoBack()) { navigation.goBack(); } else { navigation.reset({ index: 0, routes: [{ name: 'MainNavigation' }], }); } } catch (error) { Alert.alert("Could not delete group", "Please try again."); } finally { setIsDeletingGroup(false); } } } ] ); }; const header = ( { //setShowNewPost(!showNewPost); navigation.navigate('NewPost', {toProfile: profile._id}) }} /> {isOwnedGroup ? ( ) : <>} { showNewPost ? setPosts([newPost, ...Posts])} /> : <> } ) return ( {(Posts.length !== 0 || profile._id) ? item.lastUpdated || item._id || item.createdAt} ListHeaderComponent={header} refreshing={loading} initialNumToRender={3} maxToRenderPerBatch={3} removeClippedSubviews={true} onRefresh={() => { logProfile('refresh:start', { profileid: route?.params?.profileid || null, tag, }); setLoading(true); Promise.all([ API.getUserProfile(route.params.profileid, true), API.getPosts(route.params.profileid), ]).then(([profileObj, data]) => { const nextProfile = profileObj && profileObj._id ? profileObj : {}; const profileData = nextProfile.profile || {}; const safePosts = Array.isArray(data) ? data : []; setProfile(nextProfile); navigation.setOptions({ title: (profileData.firstName || "") + " " + (profileData.lastName || "") }); setPosts(safePosts); storeProfilePosts(route.params.profileid, safePosts); setLoading(false); logProfile('refresh:end', { profileid: route.params.profileid, count: safePosts.length, cached: false, }); }).catch(() => { setLoading(false); }); }} /> : <> //TODO: Add empty profile card here } ); } export default Profile; const styles = StyleSheet.create({ container: { flex: 1, backgroundColor: "#edf2f7", }, deleteGroupRow: { paddingHorizontal: 12, paddingTop: 12, }, });