// import spinner from "@/assets/icons/spinner.svg"; import Composer from "@/components/composer/Composer"; import PostList from "@/components/feed/PostList"; import Profile from "@/components/profile/Profile"; import useLocalState, { useStore } from "@/state/state"; import Icon from "@/components/Icon"; import toast from "react-hot-toast"; import { useState } from "react"; import type { FC } from "@/types/trill"; import type { UserType } from "@/types/nostrill"; import { isValidPatp } from "urbit-ob"; import { isValidNostrPubkey } from "@/logic/nostrill"; import { ErrorPage } from "@/Router"; function UserLoader({ userString }: { userString: string }) { const { api, pubkey } = useLocalState((s) => ({ api: s.api, pubkey: s.pubkey, })); // auto updating on SSE doesn't work if we do shallow const user = isValidPatp(userString) ? { urbit: userString } : isValidNostrPubkey(userString) ? { nostr: userString } : { error: "" }; const isOwnProfile = "urbit" in user ? user.urbit === api?.airlock.our : "nostr" in user ? pubkey === user.nostr : false; if ("error" in user) return ; else return ; } function UserFeed({ user, userString, isMe, }: { user: UserType; userString: string; isMe: boolean; }) { const { api, addProfile } = useLocalState((s) => ({ api: s.api, addProfile: s.addProfile, })); // auto updating on SSE doesn't work if we do shallow const { following } = useStore(); const feed = following.get(userString); const refetch = () => feed; const isFollowing = following.has(userString); const [isFollowLoading, setIsFollowLoading] = useState(false); const [isAccessLoading, setIsAccessLoading] = useState(false); const [fc, setFC] = useState(); const handleFollow = async () => { if (!api) return; setIsFollowLoading(true); try { if (isFollowing) { await api.unfollow(user); toast.success(`Unfollowed ${userString}`); } else { await api.follow(user); toast.success(`Now following ${userString}`); } } catch (error) { toast.error( `Failed to ${isFollowing ? "unfollow" : "follow"} ${userString}`, ); console.error("Follow error:", error); } finally { setIsFollowLoading(false); } }; const handleRequestAccess = async () => { if (!api) return; if (!("urbit" in user)) return; setIsAccessLoading(true); try { const res = await api.peekFeed(user.urbit); toast.success(`Access request sent to ${user.urbit}`); if ("error" in res) toast.error(res.error); else { console.log("peeked", res.ok.feed); setFC(res.ok.feed); if (res.ok.profile) addProfile(userString, res.ok.profile); } } catch (error) { toast.error(`Failed to request access from ${user.urbit}`); console.error("Access request error:", error); } finally { setIsAccessLoading(false); } }; return ( {!isMe && ( {isFollowLoading ? ( <> {isFollowing ? "Unfollowing..." : "Following..."} > ) : ( <> {isFollowing ? "Unfollow" : "Follow"} > )} {isAccessLoading ? ( <> Requesting... > ) : ( <> Request Access > )} )} {feed ? ( ) : fc ? ( ) : null} {!isMe && !feed && !fc && ( No Posts Available This user's posts are not publicly visible. {!isFollowing && " Try following them"} or request temporary access to see their content. )} ); } export default UserLoader;
This user's posts are not publicly visible. {!isFollowing && " Try following them"} or request temporary access to see their content.