import Layout from "@/components/Layout"; import { useAuth } from "@/contexts/AuthContext"; import { useEffect, useState } from "react"; import { Navigate } from "react-router-dom"; import LoadingScreen from "@/components/LoadingScreen"; import { Button } from "@/components/ui/button"; import { Card, CardContent } from "@/components/ui/card"; import { Avatar, AvatarFallback, AvatarImage } from "@/components/ui/avatar"; import { aethexSocialService } from "@/lib/aethex-social-service"; import { communityService, realtimeService } from "@/lib/supabase-service"; import PostComposer from "@/components/social/PostComposer"; import { useToast } from "@/hooks/use-toast"; import { Heart, MessageCircle, Share2, UserPlus, UserCheck, Volume2, VolumeX, } from "lucide-react"; interface FeedItem { id: string; authorId: string; authorName: string; authorAvatar?: string | null; caption?: string; mediaUrl?: string | null; mediaType: "video" | "image" | "none"; likes: number; comments: number; } function parseContent(content: string): { text?: string; mediaUrl?: string | null; mediaType: "video" | "image" | "none"; } { try { const obj = JSON.parse(content || "{}"); return { text: obj.text || content, mediaUrl: obj.mediaUrl || null, mediaType: obj.mediaType || (obj.mediaUrl ? /(mp4|webm|mov)$/i.test(obj.mediaUrl) ? "video" : "image" : "none"), }; } catch { return { text: content, mediaUrl: null, mediaType: "none" }; } } export default function Feed() { const { user, loading } = useAuth(); const { toast } = useToast(); const [isLoading, setIsLoading] = useState(true); const [following, setFollowing] = useState([]); const [items, setItems] = useState([]); const [muted, setMuted] = useState(true); useEffect(() => { const load = async () => { setIsLoading(true); try { const posts = await communityService.getPosts(20); if (user?.id) { const flw = await aethexSocialService.getFollowing(user.id); setFollowing(flw); } else { setFollowing([]); } const mapped: FeedItem[] = posts.map((p: any) => { const meta = parseContent(p.content); const author = p.user_profiles || {}; return { id: p.id, authorId: p.author_id, authorName: author.full_name || author.username || "User", authorAvatar: author.avatar_url, caption: meta.text, mediaUrl: meta.mediaUrl, mediaType: meta.mediaType, likes: p.likes_count ?? 0, comments: p.comments_count ?? 0, }; }); // If no posts yet, fall back to recommended people as placeholders if (mapped.length === 0) { const recs = await aethexSocialService.listRecommended( user?.id || "guest", 12, ); const placeholders: FeedItem[] = recs.map((r: any) => ({ id: r.id, authorId: r.id, authorName: r.full_name || r.username || "User", authorAvatar: r.avatar_url, caption: r.bio || "", mediaUrl: r.banner_url || r.avatar_url || null, mediaType: r.banner_url?.match(/\.(mp4|webm|mov)(\?.*)?$/i) ? "video" : r.banner_url || r.avatar_url ? "image" : "none", likes: Math.floor(Math.random() * 200) + 5, comments: Math.floor(Math.random() * 30), })); setItems(placeholders); } else { setItems(mapped); } } finally { setIsLoading(false); } }; load(); let cleanup: any = null; try { const sub = realtimeService.subscribeToCommunityPosts(() => load()); cleanup = () => { try { sub.unsubscribe?.(); } catch {} }; } catch {} return () => { cleanup?.(); }; }, [user, loading]); const isFollowingAuthor = (id: string) => following.includes(id); const toggleFollow = async (targetId: string) => { if (!user) return; if (isFollowingAuthor(targetId)) { await aethexSocialService.unfollowUser(user.id, targetId); setFollowing((s) => s.filter((x) => x !== targetId)); } else { await aethexSocialService.followUser(user.id, targetId); setFollowing((s) => Array.from(new Set([...s, targetId]))); } }; const share = async (id: string) => { const url = `${location.origin}/feed#post-${id}`; try { if ((navigator as any).share) { await (navigator as any).share({ title: "AeThex", text: "Check this post", url, }); } else { await navigator.clipboard.writeText(url); toast({ description: "Link copied" }); } } catch {} }; // Guests can view the feed with demo content if (loading || isLoading) { return ( ); } return (
setIsLoading(true)} />
{items.length === 0 && (
No posts yet. Share something to start the feed.
)} {items.map((item) => (
{item.mediaType === "video" && item.mediaUrl ? (
))}
); }