diff --git a/src/app/api/node/route.ts b/src/app/api/node/route.ts index 2591416..e5293a2 100644 --- a/src/app/api/node/route.ts +++ b/src/app/api/node/route.ts @@ -34,7 +34,7 @@ export async function GET() { if (!node) { return NextResponse.json({ name: process.env.NEXT_PUBLIC_NODE_NAME || 'Synapsis Node', - description: process.env.NEXT_PUBLIC_NODE_DESCRIPTION || 'A federated social network node.', + description: process.env.NEXT_PUBLIC_NODE_DESCRIPTION || 'A swarm social network node.', accentColor: process.env.NEXT_PUBLIC_ACCENT_COLOR || '#FFFFFF', domain, admins, @@ -52,7 +52,7 @@ export async function GET() { console.error('Node info error:', error); return NextResponse.json({ name: process.env.NEXT_PUBLIC_NODE_NAME || 'Synapsis Node', - description: process.env.NEXT_PUBLIC_NODE_DESCRIPTION || 'A federated social network node.', + description: process.env.NEXT_PUBLIC_NODE_DESCRIPTION || 'A swarm social network node.', admins: [], }); } diff --git a/src/app/chat/page.tsx b/src/app/chat/page.tsx index 6682176..f52c29f 100644 --- a/src/app/chat/page.tsx +++ b/src/app/chat/page.tsx @@ -61,6 +61,28 @@ export default function ChatPage() { const [encryptionChecked, setEncryptionChecked] = useState(false); const messagesEndRef = useRef(null); + const messagesContainerRef = useRef(null); + const [isAtBottom, setIsAtBottom] = useState(true); + + // Check if user is scrolled to bottom + const checkIfAtBottom = () => { + if (!messagesContainerRef.current) return true; + const { scrollTop, scrollHeight, clientHeight } = messagesContainerRef.current; + const threshold = 100; // pixels from bottom + return scrollHeight - scrollTop - clientHeight < threshold; + }; + + // Handle scroll to track if user is at bottom + const handleScroll = () => { + setIsAtBottom(checkIfAtBottom()); + }; + + // Scroll to bottom manually + const scrollToBottom = () => { + if (messagesEndRef.current) { + messagesEndRef.current.scrollIntoView({ behavior: 'smooth' }); + } + }; // Wait for encryption to be ready before showing UI useEffect(() => { @@ -106,12 +128,12 @@ export default function ChatPage() { } }, [selectedConversation, hasKeys]); - // Auto-scroll to bottom of messages + // Auto-scroll to bottom of messages only if user was already at bottom useEffect(() => { - if (messagesEndRef.current) { + if (messagesEndRef.current && isAtBottom) { messagesEndRef.current.scrollIntoView({ behavior: 'smooth' }); } - }, [messages]); + }, [messages, isAtBottom]); const fetchRecipientKey = async (handle: string) => { try { @@ -439,9 +461,9 @@ export default function ChatPage() { // Thread View if (selectedConversation) { return ( - <> +
{/* Header */} -
+
{/* Messages */} -
+
{messages.map(msg => (
+ + {/* Scroll to bottom button */} + {!isAtBottom && ( + + )}
{/* Input */} -
+
- +
); } diff --git a/src/app/page.tsx b/src/app/page.tsx index 906482c..09688b4 100644 --- a/src/app/page.tsx +++ b/src/app/page.tsx @@ -27,7 +27,7 @@ export default function Home() { const [loadingMore, setLoadingMore] = useState(false); const [nextCursor, setNextCursor] = useState(null); const [replyingTo, setReplyingTo] = useState(null); - const [feedType, setFeedType] = useState<'latest' | 'curated'>('latest'); + const [feedType, setFeedType] = useState<'following' | 'curated'>('following'); const [feedMeta, setFeedMeta] = useState<{ algorithm: string; windowHours: number; @@ -49,7 +49,7 @@ export default function Home() { } }, [user, router]); - const loadFeed = async (type: 'latest' | 'curated', cursor?: string | null) => { + const loadFeed = async (type: 'following' | 'curated', cursor?: string | null) => { if (cursor) { setLoadingMore(true); } else { @@ -175,10 +175,10 @@ export default function Home() {

Home

+
diff --git a/src/components/RightSidebar.tsx b/src/components/RightSidebar.tsx index e4a44d7..f421e3c 100644 --- a/src/components/RightSidebar.tsx +++ b/src/components/RightSidebar.tsx @@ -10,7 +10,7 @@ interface Admin { } export function RightSidebar() { - const fallbackDescription = process.env.NEXT_PUBLIC_NODE_DESCRIPTION || 'A federated social network node.'; + const fallbackDescription = process.env.NEXT_PUBLIC_NODE_DESCRIPTION || 'A swarm social network node.'; const [nodeInfo, setNodeInfo] = useState({ name: process.env.NEXT_PUBLIC_NODE_NAME || 'Synapsis Node', description: fallbackDescription,