botchan 0.1.0 → 0.1.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +52 -17
- package/dist/cli/index.mjs +10 -9
- package/dist/cli/index.mjs.map +1 -1
- package/dist/tui/index.mjs +10 -9
- package/dist/tui/index.mjs.map +1 -1
- package/package.json +2 -2
package/dist/tui/index.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/tui/hooks/useFeedData.ts","../../src/tui/hooks/useKeyboard.ts","../../src/tui/hooks/useViewport.ts","../../src/tui/components/FeedList.tsx","../../src/tui/components/PostList.tsx","../../src/tui/components/CommentTree.tsx","../../src/tui/components/Profile.tsx","../../src/tui/components/Header.tsx","../../src/tui/components/StatusBar.tsx","../../src/tui/components/PostInput.tsx","../../src/tui/components/SenderFilter.tsx","../../src/utils/config.ts","../../src/utils/state.ts","../../src/tui/components/FeedSearch.tsx","../../src/tui/components/Help.tsx","../../src/tui/App.tsx","../../src/tui/index.tsx"],"names":["useState","useRef","useCallback","useEffect","jsx","Box","Text","jsxs","truncateAddress","formatTimestamp","useStdout","React","isAddress","formatFeedName","useInput"],"mappings":"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","file":"index.mjs","sourcesContent":["import { useState, useEffect, useCallback, useRef } from \"react\";\nimport {\n FeedClient,\n FeedRegistryClient,\n generatePostHash,\n parseCommentData,\n} from \"@net-protocol/feeds\";\nimport { NetClient, NULL_ADDRESS } from \"@net-protocol/core\";\nimport type { RegisteredFeed, NetMessage } from \"@net-protocol/feeds\";\n\n/** Comment with depth info for tree display */\nexport interface CommentWithDepth {\n comment: NetMessage;\n depth: number;\n replyToKey: string | null; // \"sender:timestamp\" of parent comment, or null for top-level\n}\n\ninterface FeedDataOptions {\n chainId: number;\n rpcUrl?: string;\n}\n\n/**\n * Hook to fetch registered feeds\n */\nexport function useFeeds(options: FeedDataOptions) {\n const [feeds, setFeeds] = useState<RegisteredFeed[]>([]);\n const [loading, setLoading] = useState(true);\n const [error, setError] = useState<Error | null>(null);\n\n const fetchFeeds = useCallback(async () => {\n setLoading(true);\n setError(null);\n\n try {\n const client = new FeedRegistryClient({\n chainId: options.chainId,\n overrides: options.rpcUrl ? { rpcUrls: [options.rpcUrl] } : undefined,\n });\n\n const result = await client.getRegisteredFeeds({ maxFeeds: 100 });\n setFeeds(result);\n } catch (err) {\n setError(err instanceof Error ? err : new Error(String(err)));\n } finally {\n setLoading(false);\n }\n }, [options.chainId, options.rpcUrl]);\n\n useEffect(() => {\n fetchFeeds();\n }, [fetchFeeds]);\n\n return { feeds, loading, error, refetch: fetchFeeds };\n}\n\ninterface UsePostsOptions extends FeedDataOptions {\n senderFilter?: string;\n}\n\n/**\n * Hook to fetch posts for a feed\n */\nexport function usePosts(feedName: string | null, options: UsePostsOptions) {\n const [posts, setPosts] = useState<NetMessage[]>([]);\n const [commentCounts, setCommentCounts] = useState<Map<string, number>>(\n new Map()\n );\n const [loading, setLoading] = useState(false);\n const [error, setError] = useState<Error | null>(null);\n\n const fetchPosts = useCallback(async () => {\n if (!feedName) {\n setPosts([]);\n setCommentCounts(new Map());\n return;\n }\n\n setLoading(true);\n setError(null);\n\n try {\n const client = new FeedClient({\n chainId: options.chainId,\n overrides: options.rpcUrl ? { rpcUrls: [options.rpcUrl] } : undefined,\n });\n\n // Check post count first to avoid InvalidRange error on empty feeds\n const postCount = await client.getFeedPostCount(feedName);\n if (postCount === 0) {\n setPosts([]);\n setCommentCounts(new Map());\n setLoading(false);\n return;\n }\n\n // Fetch more posts if filtering by sender\n const fetchLimit = options.senderFilter ? 200 : 50;\n let result = await client.getFeedPosts({ topic: feedName, maxPosts: fetchLimit });\n\n // Filter by sender if specified\n if (options.senderFilter) {\n const senderLower = options.senderFilter.toLowerCase();\n result = result.filter(\n (post) => post.sender.toLowerCase() === senderLower\n );\n }\n\n setPosts(result);\n\n // Fetch comment counts in batch (single RPC call)\n if (result.length > 0) {\n const batchCounts = await client.getCommentCountBatch(result);\n // Convert from post hash keys to sender:timestamp keys for compatibility\n const counts = new Map<string, number>();\n for (const post of result) {\n const postHash = generatePostHash(post);\n const key = `${post.sender}:${post.timestamp}`;\n counts.set(key, batchCounts.get(postHash) ?? 0);\n }\n setCommentCounts(counts);\n } else {\n setCommentCounts(new Map());\n }\n } catch (err) {\n setError(err instanceof Error ? err : new Error(String(err)));\n } finally {\n setLoading(false);\n }\n }, [feedName, options.chainId, options.rpcUrl, options.senderFilter]);\n\n useEffect(() => {\n fetchPosts();\n }, [fetchPosts]);\n\n return { posts, commentCounts, loading, error, refetch: fetchPosts };\n}\n\n/**\n * Build a flat list with depth info from comments by parsing replyTo relationships.\n * Returns comments in tree order (parent followed by children, depth-first).\n */\nfunction buildCommentTree(rawComments: NetMessage[]): CommentWithDepth[] {\n // Parse replyTo for each comment\n const commentMap = new Map<string, { comment: NetMessage; replyToKey: string | null }>();\n const childrenMap = new Map<string, string[]>(); // parent key -> child keys\n\n for (const comment of rawComments) {\n const key = `${comment.sender}:${comment.timestamp}`;\n let replyToKey: string | null = null;\n\n // Parse the data field to get replyTo info\n try {\n const commentData = parseCommentData(comment.data as `0x${string}`);\n if (commentData?.replyTo) {\n replyToKey = `${commentData.replyTo.sender}:${commentData.replyTo.timestamp}`;\n }\n } catch {\n // Failed to parse, treat as top-level\n }\n\n commentMap.set(key, { comment, replyToKey });\n\n // Build children map\n const parentKey = replyToKey ?? \"__root__\";\n if (!childrenMap.has(parentKey)) {\n childrenMap.set(parentKey, []);\n }\n childrenMap.get(parentKey)!.push(key);\n }\n\n // DFS to build flat list in tree order\n const result: CommentWithDepth[] = [];\n\n function traverse(parentKey: string, depth: number) {\n const children = childrenMap.get(parentKey) ?? [];\n for (const childKey of children) {\n const item = commentMap.get(childKey);\n if (item) {\n result.push({\n comment: item.comment,\n depth,\n replyToKey: item.replyToKey,\n });\n traverse(childKey, depth + 1);\n }\n }\n }\n\n // Start from root (top-level comments)\n traverse(\"__root__\", 0);\n\n // Handle orphaned comments (replies to comments not in our set)\n // Add them at the end as top-level\n const addedKeys = new Set(result.map((r) => `${r.comment.sender}:${r.comment.timestamp}`));\n for (const [key, item] of commentMap) {\n if (!addedKeys.has(key)) {\n result.push({\n comment: item.comment,\n depth: 0, // Show as top-level since parent is missing\n replyToKey: item.replyToKey,\n });\n }\n }\n\n return result;\n}\n\n/**\n * Hook to fetch comments for a post\n */\nexport function useComments(post: NetMessage | null, options: FeedDataOptions) {\n const [comments, setComments] = useState<CommentWithDepth[]>([]);\n const [replyCounts, setReplyCounts] = useState<Map<string, number>>(\n new Map()\n );\n const [loading, setLoading] = useState(false);\n const [error, setError] = useState<Error | null>(null);\n\n // Track which post the current data belongs to\n const loadedPostRef = useRef<string | null>(null);\n const currentPostKey = post ? `${post.sender}:${post.timestamp}` : null;\n\n // Determine if we should show loading state:\n // - If post exists but doesn't match the loaded data, we're in a loading state\n // - Or if explicitly loading\n const isLoading = loading || (currentPostKey !== null && currentPostKey !== loadedPostRef.current);\n\n // Set loading immediately when post changes to avoid flash\n useEffect(() => {\n if (post) {\n setLoading(true);\n setComments([]);\n setReplyCounts(new Map());\n }\n }, [post]);\n\n const fetchComments = useCallback(async () => {\n if (!post) {\n setComments([]);\n setReplyCounts(new Map());\n setLoading(false);\n loadedPostRef.current = null;\n return;\n }\n\n const postKey = `${post.sender}:${post.timestamp}`;\n setLoading(true);\n setError(null);\n\n try {\n const client = new FeedClient({\n chainId: options.chainId,\n overrides: options.rpcUrl ? { rpcUrls: [options.rpcUrl] } : undefined,\n });\n\n // Check comment count first to avoid InvalidRange error\n const commentCount = await client.getCommentCount(post);\n if (commentCount === 0) {\n setComments([]);\n setReplyCounts(new Map());\n loadedPostRef.current = postKey;\n setLoading(false);\n return;\n }\n\n // Fetch all comments (increase limit to get full tree)\n const result = await client.getComments({ post, maxComments: 200 });\n\n // Build tree structure\n const treeComments = buildCommentTree(result);\n setComments(treeComments);\n\n // Fetch reply counts for each comment in batch\n if (result.length > 0) {\n const batchCounts = await client.getCommentCountBatch(result);\n // Convert from post hash keys to sender:timestamp keys\n const counts = new Map<string, number>();\n for (const comment of result) {\n const commentHash = generatePostHash(comment);\n const key = `${comment.sender}:${comment.timestamp}`;\n counts.set(key, batchCounts.get(commentHash) ?? 0);\n }\n setReplyCounts(counts);\n } else {\n setReplyCounts(new Map());\n }\n\n // Mark this post as loaded\n loadedPostRef.current = postKey;\n } catch (err) {\n setError(err instanceof Error ? err : new Error(String(err)));\n } finally {\n setLoading(false);\n }\n }, [post, options.chainId, options.rpcUrl]);\n\n useEffect(() => {\n fetchComments();\n }, [fetchComments]);\n\n return { comments, replyCounts, loading: isLoading, error, refetch: fetchComments };\n}\n\n/** Profile message with topic (feed name) for display */\nexport interface ProfileMessage {\n message: NetMessage;\n topic: string;\n}\n\n/**\n * Hook to fetch recent activity for an address (profile view)\n */\nexport function useProfile(address: string | null, options: FeedDataOptions) {\n const [messages, setMessages] = useState<ProfileMessage[]>([]);\n const [loading, setLoading] = useState(false);\n const [error, setError] = useState<Error | null>(null);\n\n // Track which address the current data belongs to\n const loadedAddressRef = useRef<string | null>(null);\n\n // Determine if we should show loading state\n const isLoading = loading || (address !== null && address !== loadedAddressRef.current);\n\n // Set loading immediately when address changes\n useEffect(() => {\n if (address) {\n setLoading(true);\n setMessages([]);\n }\n }, [address]);\n\n const fetchProfile = useCallback(async () => {\n if (!address) {\n setMessages([]);\n setLoading(false);\n loadedAddressRef.current = null;\n return;\n }\n\n setLoading(true);\n setError(null);\n\n try {\n const client = new NetClient({\n chainId: options.chainId,\n overrides: options.rpcUrl ? { rpcUrls: [options.rpcUrl] } : undefined,\n });\n\n // Get message count for this user from feeds (app = NULL_ADDRESS)\n const count = await client.getMessageCount({\n filter: {\n appAddress: NULL_ADDRESS as `0x${string}`,\n maker: address as `0x${string}`,\n },\n });\n\n if (count === 0) {\n setMessages([]);\n loadedAddressRef.current = address;\n setLoading(false);\n return;\n }\n\n // Fetch last 50 messages\n const limit = 50;\n const startIndex = count > limit ? count - limit : 0;\n\n const rawMessages = await client.getMessages({\n filter: {\n appAddress: NULL_ADDRESS as `0x${string}`,\n maker: address as `0x${string}`,\n },\n startIndex,\n endIndex: count,\n });\n\n // Convert to ProfileMessage with topic\n const profileMessages: ProfileMessage[] = rawMessages.map((msg) => ({\n message: msg,\n topic: msg.topic ?? \"unknown\",\n }));\n\n // Sort by most recent first\n profileMessages.sort((a, b) => Number(b.message.timestamp - a.message.timestamp));\n\n setMessages(profileMessages);\n loadedAddressRef.current = address;\n } catch (err) {\n setError(err instanceof Error ? err : new Error(String(err)));\n } finally {\n setLoading(false);\n }\n }, [address, options.chainId, options.rpcUrl]);\n\n useEffect(() => {\n fetchProfile();\n }, [fetchProfile]);\n\n return { messages, loading: isLoading, error, refetch: fetchProfile };\n}\n","import { useState, useCallback, useRef } from \"react\";\nimport { useInput } from \"ink\";\nimport type { NetMessage } from \"@net-protocol/feeds\";\n\nexport type ViewMode = \"feeds\" | \"posts\" | \"comments\" | \"compose\" | \"filter\" | \"search\" | \"profile\";\n\n/** Navigation stack entry - captures full state for back navigation */\nexport interface NavEntry {\n viewMode: ViewMode;\n feedName: string | null;\n post: NetMessage | null;\n profileAddress: string | null;\n senderFilter: string | undefined;\n selectedFeedIndex: number;\n selectedPostIndex: number;\n selectedCommentIndex: number;\n selectedProfileIndex: number;\n}\n\ninterface NavigationState {\n viewMode: ViewMode;\n selectedFeedIndex: number;\n selectedPostIndex: number;\n selectedCommentIndex: number;\n selectedProfileIndex: number;\n}\n\ninterface UseKeyboardOptions {\n feedsCount: number;\n postsCount: number;\n commentsCount: number;\n profileItemsCount: number;\n // Current context for stack snapshots\n currentFeedName: string | null;\n currentPost: NetMessage | null;\n currentProfileAddress: string | null;\n currentSenderFilter: string | undefined;\n // Callbacks\n onQuit: () => void;\n onRefresh: () => void;\n onCompose?: () => void;\n onFilter?: () => void;\n onSearch?: () => void;\n onSelectFeed?: (index: number) => void;\n onSelectPost?: (index: number) => void;\n onViewProfile?: () => void;\n onSelectProfileItem?: (index: number) => void;\n onGoHome?: () => void;\n onRestoreState?: (entry: NavEntry) => void;\n onToggleUserFilter?: () => void;\n onShowHelp?: () => void;\n}\n\n/**\n * Hook to handle keyboard navigation in TUI with navigation stack\n */\nexport function useKeyboard(options: UseKeyboardOptions) {\n const [state, setState] = useState<NavigationState>({\n viewMode: \"feeds\",\n selectedFeedIndex: 0,\n selectedPostIndex: 0,\n selectedCommentIndex: 0,\n selectedProfileIndex: 0,\n });\n\n // Navigation stack for back button behavior\n const navStackRef = useRef<NavEntry[]>([]);\n\n // Create a snapshot of current state for the stack\n const createSnapshot = useCallback((): NavEntry => {\n return {\n viewMode: state.viewMode,\n feedName: options.currentFeedName,\n post: options.currentPost,\n profileAddress: options.currentProfileAddress,\n senderFilter: options.currentSenderFilter,\n selectedFeedIndex: state.selectedFeedIndex,\n selectedPostIndex: state.selectedPostIndex,\n selectedCommentIndex: state.selectedCommentIndex,\n selectedProfileIndex: state.selectedProfileIndex,\n };\n }, [state, options.currentFeedName, options.currentPost, options.currentProfileAddress, options.currentSenderFilter]);\n\n // Push current state to stack before navigating forward\n const pushAndNavigate = useCallback((newViewMode: ViewMode, resetIndex?: { key: keyof NavigationState; value: number }) => {\n // Save current state to stack\n navStackRef.current.push(createSnapshot());\n\n setState((prev) => {\n const newState = { ...prev, viewMode: newViewMode };\n if (resetIndex) {\n (newState as any)[resetIndex.key] = resetIndex.value;\n }\n return newState;\n });\n }, [createSnapshot]);\n\n const navigateUp = useCallback(() => {\n setState((prev) => {\n switch (prev.viewMode) {\n case \"feeds\":\n return {\n ...prev,\n selectedFeedIndex: Math.max(0, prev.selectedFeedIndex - 1),\n };\n case \"posts\":\n return {\n ...prev,\n selectedPostIndex: Math.max(0, prev.selectedPostIndex - 1),\n };\n case \"comments\":\n return {\n ...prev,\n selectedCommentIndex: Math.max(0, prev.selectedCommentIndex - 1),\n };\n case \"profile\":\n return {\n ...prev,\n selectedProfileIndex: Math.max(0, prev.selectedProfileIndex - 1),\n };\n default:\n return prev;\n }\n });\n }, []);\n\n const navigateDown = useCallback(() => {\n setState((prev) => {\n switch (prev.viewMode) {\n case \"feeds\":\n return {\n ...prev,\n selectedFeedIndex: Math.min(\n options.feedsCount - 1,\n prev.selectedFeedIndex + 1\n ),\n };\n case \"posts\":\n return {\n ...prev,\n selectedPostIndex: Math.min(\n options.postsCount - 1,\n prev.selectedPostIndex + 1\n ),\n };\n case \"comments\":\n return {\n ...prev,\n selectedCommentIndex: Math.min(\n options.commentsCount - 1,\n prev.selectedCommentIndex + 1\n ),\n };\n case \"profile\":\n return {\n ...prev,\n selectedProfileIndex: Math.min(\n options.profileItemsCount - 1,\n prev.selectedProfileIndex + 1\n ),\n };\n default:\n return prev;\n }\n });\n }, [options.feedsCount, options.postsCount, options.commentsCount, options.profileItemsCount]);\n\n const selectItem = useCallback(() => {\n switch (state.viewMode) {\n case \"feeds\":\n if (options.onSelectFeed) {\n options.onSelectFeed(state.selectedFeedIndex);\n }\n pushAndNavigate(\"posts\", { key: \"selectedPostIndex\", value: 0 });\n break;\n case \"posts\":\n if (options.onSelectPost) {\n options.onSelectPost(state.selectedPostIndex);\n }\n pushAndNavigate(\"comments\", { key: \"selectedCommentIndex\", value: 0 });\n break;\n case \"profile\":\n if (options.onSelectProfileItem) {\n options.onSelectProfileItem(state.selectedProfileIndex);\n }\n pushAndNavigate(\"posts\", { key: \"selectedPostIndex\", value: 0 });\n break;\n default:\n break;\n }\n }, [state.viewMode, state.selectedFeedIndex, state.selectedPostIndex, state.selectedProfileIndex, options.onSelectFeed, options.onSelectPost, options.onSelectProfileItem, pushAndNavigate]);\n\n const goBack = useCallback(() => {\n // For compose/filter/search, just go back to posts without popping stack\n if (state.viewMode === \"compose\" || state.viewMode === \"filter\") {\n setState((prev) => ({ ...prev, viewMode: \"posts\" }));\n return;\n }\n\n // Pop from stack and restore state\n const previousEntry = navStackRef.current.pop();\n if (previousEntry && options.onRestoreState) {\n options.onRestoreState(previousEntry);\n setState({\n viewMode: previousEntry.viewMode,\n selectedFeedIndex: previousEntry.selectedFeedIndex,\n selectedPostIndex: previousEntry.selectedPostIndex,\n selectedCommentIndex: previousEntry.selectedCommentIndex,\n selectedProfileIndex: previousEntry.selectedProfileIndex,\n });\n } else if (state.viewMode !== \"feeds\") {\n // Fallback: go to feeds if stack is empty\n setState((prev) => ({ ...prev, viewMode: \"feeds\" }));\n }\n }, [state.viewMode, options.onRestoreState]);\n\n const startCompose = useCallback(() => {\n if (options.onCompose) {\n setState((prev) => ({ ...prev, viewMode: \"compose\" }));\n options.onCompose();\n }\n }, [options.onCompose]);\n\n const startFilter = useCallback(() => {\n if (options.onFilter) {\n setState((prev) => ({ ...prev, viewMode: \"filter\" }));\n options.onFilter();\n }\n }, [options.onFilter]);\n\n const startSearch = useCallback(() => {\n if (options.onSearch) {\n // Push current state before search\n navStackRef.current.push(createSnapshot());\n setState((prev) => ({ ...prev, viewMode: \"search\" }));\n options.onSearch();\n }\n }, [options.onSearch, createSnapshot]);\n\n const viewProfile = useCallback(() => {\n if (options.onViewProfile) {\n pushAndNavigate(\"profile\", { key: \"selectedProfileIndex\", value: 0 });\n options.onViewProfile();\n }\n }, [options.onViewProfile, pushAndNavigate]);\n\n const goHome = useCallback(() => {\n // Clear the stack when going home\n navStackRef.current = [];\n if (options.onGoHome) {\n options.onGoHome();\n }\n setState({\n viewMode: \"feeds\",\n selectedFeedIndex: 0,\n selectedPostIndex: 0,\n selectedCommentIndex: 0,\n selectedProfileIndex: 0,\n });\n }, [options.onGoHome]);\n\n useInput((input, key) => {\n // Don't handle input in compose, filter, or search mode\n if (state.viewMode === \"compose\" || state.viewMode === \"filter\" || state.viewMode === \"search\") return;\n\n if (input === \"q\") {\n options.onQuit();\n } else if (input === \"j\" || key.downArrow) {\n navigateDown();\n } else if (input === \"k\" || key.upArrow) {\n navigateUp();\n } else if (key.return) {\n selectItem();\n } else if (key.escape) {\n goBack();\n } else if (input === \"r\") {\n options.onRefresh();\n } else if (input === \"h\") {\n goHome();\n } else if (input === \"/\") {\n startSearch();\n } else if (input === \"p\" && (state.viewMode === \"posts\" || state.viewMode === \"comments\")) {\n viewProfile();\n } else if (input === \"f\" && state.viewMode === \"posts\") {\n startFilter();\n } else if (input === \"u\" && state.viewMode === \"posts\") {\n // Toggle user filter\n if (options.onToggleUserFilter) {\n options.onToggleUserFilter();\n }\n } else if (input === \"?\") {\n // Show help\n if (options.onShowHelp) {\n options.onShowHelp();\n }\n }\n });\n\n const setViewMode = useCallback((mode: ViewMode) => {\n setState((prev) => ({ ...prev, viewMode: mode }));\n }, []);\n\n return {\n ...state,\n setViewMode,\n navigateUp,\n navigateDown,\n selectItem,\n goBack,\n };\n}\n","import { useState, useEffect } from \"react\";\nimport { useStdout } from \"ink\";\n\ninterface ViewportInfo {\n /** Terminal height in rows */\n terminalHeight: number;\n /** Available height for list items (accounting for chrome) */\n availableHeight: number;\n /** First visible item index */\n startIndex: number;\n /** Last visible item index (exclusive) */\n endIndex: number;\n}\n\ninterface UseViewportOptions {\n /** Total number of items */\n itemCount: number;\n /** Currently selected index */\n selectedIndex: number;\n /** Lines reserved for header/footer chrome */\n reservedLines?: number;\n /** Estimated lines per item (for variable height items) */\n linesPerItem?: number;\n}\n\n/**\n * Hook to calculate visible viewport for scrollable lists\n */\nexport function useViewport({\n itemCount,\n selectedIndex,\n reservedLines = 6, // header, status bar, padding, etc.\n linesPerItem = 3, // most items are 2-3 lines (content + metadata + margin)\n}: UseViewportOptions): ViewportInfo {\n const { stdout } = useStdout();\n const [terminalHeight, setTerminalHeight] = useState(stdout?.rows ?? 24);\n\n useEffect(() => {\n if (!stdout) return;\n\n const handleResize = () => {\n setTerminalHeight(stdout.rows);\n };\n\n // Initial size\n setTerminalHeight(stdout.rows);\n\n // Listen for resize\n stdout.on(\"resize\", handleResize);\n return () => {\n stdout.off(\"resize\", handleResize);\n };\n }, [stdout]);\n\n const availableHeight = Math.max(terminalHeight - reservedLines, 5);\n const visibleItemCount = Math.max(Math.floor(availableHeight / linesPerItem), 1);\n\n // Calculate window that keeps selected item visible\n // Try to keep selected item roughly centered, but clamp to valid range\n let startIndex = Math.max(0, selectedIndex - Math.floor(visibleItemCount / 2));\n\n // Ensure we don't go past the end\n if (startIndex + visibleItemCount > itemCount) {\n startIndex = Math.max(0, itemCount - visibleItemCount);\n }\n\n const endIndex = Math.min(startIndex + visibleItemCount, itemCount);\n\n return {\n terminalHeight,\n availableHeight,\n startIndex,\n endIndex,\n };\n}\n","import React from \"react\";\nimport { Box, Text } from \"ink\";\nimport type { RegisteredFeed } from \"@net-protocol/feeds\";\nimport { useViewport } from \"../hooks\";\n\ninterface FeedListProps {\n feeds: RegisteredFeed[];\n selectedIndex: number;\n loading: boolean;\n error: Error | null;\n}\n\nexport function FeedList({\n feeds,\n selectedIndex,\n loading,\n error,\n}: FeedListProps) {\n const { startIndex, endIndex } = useViewport({\n itemCount: feeds.length,\n selectedIndex,\n reservedLines: 7, // header + hint + status bar + padding\n linesPerItem: 1,\n });\n\n if (loading) {\n return (\n <Box flexDirection=\"column\" padding={1}>\n <Text color=\"yellow\">Loading feeds...</Text>\n </Box>\n );\n }\n\n if (error) {\n return (\n <Box flexDirection=\"column\" padding={1}>\n <Text color=\"red\">Error: {error.message}</Text>\n </Box>\n );\n }\n\n const visibleFeeds = feeds.slice(startIndex, endIndex);\n const hasMoreAbove = startIndex > 0;\n const hasMoreBelow = endIndex < feeds.length;\n\n return (\n <Box flexDirection=\"column\" padding={1}>\n <Text bold color=\"cyan\">\n Registered Feeds {feeds.length > 0 && `(${feeds.length})`}\n </Text>\n <Box marginTop={1}>\n <Text color=\"gray\" dimColor>\n Press \"/\" to search any feed or profile\n </Text>\n </Box>\n {hasMoreAbove && (\n <Text color=\"gray\" dimColor> ↑ {startIndex} more above</Text>\n )}\n <Box flexDirection=\"column\" marginTop={hasMoreAbove ? 0 : 1}>\n {feeds.length === 0 ? (\n <Text color=\"gray\">No registered feeds found</Text>\n ) : (\n visibleFeeds.map((feed, index) => {\n const actualIndex = startIndex + index;\n const isSelected = actualIndex === selectedIndex;\n return (\n <Text\n key={`${feed.feedName}-${actualIndex}`}\n color={isSelected ? \"green\" : undefined}\n bold={isSelected}\n >\n {isSelected ? \"▶ \" : \" \"}\n {feed.feedName}\n </Text>\n );\n })\n )}\n </Box>\n {hasMoreBelow && (\n <Text color=\"gray\" dimColor> ↓ {feeds.length - endIndex} more below</Text>\n )}\n </Box>\n );\n}\n","import React from \"react\";\nimport { Box, Text } from \"ink\";\nimport type { NetMessage } from \"@net-protocol/feeds\";\nimport { useViewport } from \"../hooks\";\n\ninterface PostListProps {\n feedName: string;\n posts: NetMessage[];\n commentCounts: Map<string, number>;\n selectedIndex: number;\n loading: boolean;\n error: Error | null;\n}\n\nfunction truncateAddress(address: string): string {\n if (address.length <= 12) return address;\n return `${address.slice(0, 6)}...${address.slice(-4)}`;\n}\n\nfunction isAddress(str: string): boolean {\n return /^0x[a-fA-F0-9]{40}$/.test(str);\n}\n\nfunction formatFeedName(feedName: string): string {\n // Strip \"feed-\" prefix if present\n let name = feedName;\n if (name.startsWith(\"feed-\")) {\n name = name.slice(5);\n }\n // If it's an address, truncate it\n if (isAddress(name)) {\n return `@${truncateAddress(name)}`;\n }\n return name;\n}\n\nfunction formatTimestamp(timestamp: bigint): string {\n const date = new Date(Number(timestamp) * 1000);\n return date.toLocaleString(\"en-US\", {\n month: \"short\",\n day: \"numeric\",\n hour: \"2-digit\",\n minute: \"2-digit\",\n });\n}\n\n/** Parse post text into title (first line) and body (rest) */\nfunction parsePostContent(text: string | undefined): { title: string; body: string | null } {\n if (!text) return { title: \"\", body: null };\n\n const firstNewline = text.indexOf(\"\\n\");\n if (firstNewline === -1) {\n // No newline - entire text is title\n return { title: text.trim(), body: null };\n }\n\n const title = text.slice(0, firstNewline).trim();\n const body = text.slice(firstNewline + 1).trim();\n\n return { title, body: body || null };\n}\n\n/** Truncate title for collapsed view */\nfunction truncateTitle(title: string, maxLength = 70): string {\n if (title.length <= maxLength) return title;\n return title.slice(0, maxLength - 3) + \"...\";\n}\n\nexport function PostList({\n feedName,\n posts,\n commentCounts,\n selectedIndex,\n loading,\n error,\n}: PostListProps) {\n const { startIndex, endIndex } = useViewport({\n itemCount: posts.length,\n selectedIndex,\n reservedLines: 6, // header + status bar + padding\n linesPerItem: 3, // title + metadata + margin\n });\n\n if (loading) {\n return (\n <Box flexDirection=\"column\" padding={1}>\n <Text color=\"yellow\">Loading posts...</Text>\n </Box>\n );\n }\n\n if (error) {\n return (\n <Box flexDirection=\"column\" padding={1}>\n <Text color=\"red\">Error: {error.message}</Text>\n </Box>\n );\n }\n\n if (posts.length === 0) {\n return (\n <Box flexDirection=\"column\" padding={1}>\n <Text color=\"gray\">No posts in {formatFeedName(feedName)}</Text>\n </Box>\n );\n }\n\n const visiblePosts = posts.slice(startIndex, endIndex);\n const hasMoreAbove = startIndex > 0;\n const hasMoreBelow = endIndex < posts.length;\n\n return (\n <Box flexDirection=\"column\" padding={1}>\n <Text bold color=\"cyan\">\n {formatFeedName(feedName)} ({posts.length} posts)\n </Text>\n {hasMoreAbove && (\n <Text color=\"gray\" dimColor> ↑ {startIndex} more above</Text>\n )}\n <Box flexDirection=\"column\" marginTop={hasMoreAbove ? 0 : 1}>\n {visiblePosts.map((post, index) => {\n const actualIndex = startIndex + index;\n const isSelected = actualIndex === selectedIndex;\n const postKey = `${post.sender}:${post.timestamp}`;\n const commentCount = commentCounts.get(postKey) ?? 0;\n const { title, body } = parsePostContent(post.text);\n const displayTitle = title ? truncateTitle(title) : null;\n const hasMore = body !== null;\n\n return (\n <Box\n key={postKey}\n flexDirection=\"column\"\n marginBottom={1}\n >\n <Text\n color={isSelected ? \"green\" : undefined}\n bold={isSelected}\n >\n {isSelected ? \"▶ \" : \" \"}\n {displayTitle || <Text color=\"gray\" dimColor>(no text)</Text>}\n {hasMore && <Text color=\"gray\" dimColor> [...]</Text>}\n </Text>\n <Text color=\"gray\" dimColor>\n {\" \"}\n {truncateAddress(post.sender)} · {formatTimestamp(post.timestamp)} · {commentCount} comment{commentCount !== 1 ? \"s\" : \"\"}\n </Text>\n </Box>\n );\n })}\n </Box>\n {hasMoreBelow && (\n <Text color=\"gray\" dimColor> ↓ {posts.length - endIndex} more below</Text>\n )}\n </Box>\n );\n}\n","import React from \"react\";\nimport { Box, Text, useStdout } from \"ink\";\nimport type { NetMessage } from \"@net-protocol/feeds\";\nimport type { CommentWithDepth } from \"../hooks\";\n\ninterface CommentTreeProps {\n post: NetMessage;\n comments: CommentWithDepth[];\n replyCounts: Map<string, number>;\n selectedIndex: number; // 0 = post, 1+ = comments\n loading: boolean;\n error: Error | null;\n}\n\nfunction truncateAddress(address: string): string {\n if (address.length <= 12) return address;\n return `${address.slice(0, 6)}...${address.slice(-4)}`;\n}\n\nfunction formatTimestamp(timestamp: bigint): string {\n const date = new Date(Number(timestamp) * 1000);\n return date.toLocaleString(\"en-US\", {\n month: \"short\",\n day: \"numeric\",\n hour: \"2-digit\",\n minute: \"2-digit\",\n });\n}\n\n/** Collapse multi-line text to single line for comment preview */\nfunction collapseText(text: string, maxLength = 80): string {\n const collapsed = text.replace(/\\s+/g, \" \").trim();\n if (collapsed.length <= maxLength) return collapsed;\n return collapsed.slice(0, maxLength - 3) + \"...\";\n}\n\n/** Split text into lines, accounting for terminal width wrapping */\nfunction getTextLines(text: string, width: number): string[] {\n const lines: string[] = [];\n const rawLines = text.split(\"\\n\");\n\n for (const rawLine of rawLines) {\n if (rawLine.length === 0) {\n lines.push(\"\");\n } else if (rawLine.length <= width) {\n lines.push(rawLine);\n } else {\n // Wrap long lines\n let remaining = rawLine;\n while (remaining.length > 0) {\n lines.push(remaining.slice(0, width));\n remaining = remaining.slice(width);\n }\n }\n }\n\n return lines;\n}\n\nexport function CommentTree({\n post,\n comments,\n replyCounts,\n selectedIndex,\n loading,\n error,\n}: CommentTreeProps) {\n const { stdout } = useStdout();\n const terminalHeight = stdout?.rows ?? 24;\n const terminalWidth = stdout?.columns ?? 80;\n\n // Reserve lines for header, status bar, padding\n const reservedLines = 6;\n const availableHeight = terminalHeight - reservedLines;\n\n // selectedIndex: 0 = post, 1+ = comments (comment index = selectedIndex - 1)\n const isPostSelected = selectedIndex === 0;\n const selectedCommentIndex = selectedIndex - 1;\n\n if (loading) {\n return (\n <Box flexDirection=\"column\" padding={1}>\n <Text color=\"yellow\">Loading post...</Text>\n </Box>\n );\n }\n\n if (error) {\n return (\n <Box flexDirection=\"column\" padding={1}>\n <Text color=\"red\">Error: {error.message}</Text>\n </Box>\n );\n }\n\n // Calculate post content - leave room for selector prefix \"▶ \" (2 chars) and left margin\n const contentWidth = Math.max(40, terminalWidth - 8);\n const postText = post.text ?? \"\";\n const postLines = getTextLines(postText, contentWidth);\n\n const linesPerComment = 3;\n\n // Determine how many post lines to show based on selection\n // When post is selected, show more of the post; when comment selected, show less\n const maxPostLines = isPostSelected\n ? Math.max(3, availableHeight - 6) // Leave room for header, metadata, comments header, some comments\n : 3; // Show preview when viewing comments\n\n const displayPostLines = postLines.slice(0, maxPostLines);\n const postHasMore = postLines.length > maxPostLines;\n\n // Calculate comment viewport\n // Reserve: Post header (1) + post lines + post metadata (1) + post \"more\" indicator (1 if needed)\n // + Comments header (1) + scroll indicators (2)\n const postOverhead = 1 + displayPostLines.length + 1 + (postHasMore ? 1 : 0) + 1 + 2;\n const linesForComments = Math.max(3, availableHeight - postOverhead);\n const visibleCommentCount = Math.floor(linesForComments / linesPerComment);\n\n // Calculate comment window to keep selected comment visible\n let commentStartIndex = 0;\n if (selectedCommentIndex > 0) {\n // Keep selected comment in view (only scroll when a comment is actually selected)\n commentStartIndex = Math.max(0, selectedCommentIndex - Math.floor(visibleCommentCount / 2));\n if (commentStartIndex + visibleCommentCount > comments.length) {\n commentStartIndex = Math.max(0, comments.length - visibleCommentCount);\n }\n }\n // When post is selected (selectedCommentIndex = -1), start from beginning\n const commentEndIndex = Math.min(commentStartIndex + visibleCommentCount, comments.length);\n const visibleComments = comments.slice(commentStartIndex, commentEndIndex);\n\n const hasMoreCommentsAbove = commentStartIndex > 0;\n const hasMoreCommentsBelow = commentEndIndex < comments.length;\n\n return (\n <Box flexDirection=\"column\" padding={1}>\n {/* Post section */}\n <Text bold color=\"cyan\">Post</Text>\n <Box marginLeft={1}>\n <Text color={isPostSelected ? \"green\" : undefined} bold={isPostSelected}>\n {isPostSelected ? \"▶ \" : \" \"}\n </Text>\n <Box flexDirection=\"column\" width={contentWidth}>\n {displayPostLines.length === 0 ? (\n <Text color=\"gray\">(no text)</Text>\n ) : (\n displayPostLines.map((line, i) => (\n <Text key={i} color={isPostSelected ? \"green\" : undefined} wrap=\"truncate-end\">\n {line || \" \"}\n </Text>\n ))\n )}\n {postHasMore && (\n <Text color=\"gray\" dimColor>\n {isPostSelected ? \"↓ \" : \"↑ \"}{postLines.length - maxPostLines} more lines\n </Text>\n )}\n </Box>\n </Box>\n <Text color=\"gray\">\n {\" \"}{truncateAddress(post.sender)} · {formatTimestamp(post.timestamp)}\n </Text>\n\n {/* Comments section */}\n <Box marginTop={1}>\n <Text bold color=\"cyan\">Comments ({comments.length})</Text>\n </Box>\n\n {comments.length === 0 ? (\n <Box marginTop={1} marginLeft={1}>\n <Text color=\"gray\">No comments yet</Text>\n </Box>\n ) : (\n <Box flexDirection=\"column\">\n {hasMoreCommentsAbove && (\n <Text color=\"gray\" dimColor>\n {\" ↑ \"}{commentStartIndex} more above\n </Text>\n )}\n {visibleComments.map((item, index) => {\n const actualIndex = commentStartIndex + index;\n const isSelected = actualIndex === selectedCommentIndex;\n const { comment, depth } = item;\n const key = `${comment.sender}:${comment.timestamp}`;\n const replyCount = replyCounts.get(key) ?? 0;\n const displayText = comment.text ? collapseText(comment.text) : null;\n\n // Indentation based on nesting depth\n const indent = \" \".repeat(depth);\n const replyIndicator = depth > 0 ? \"↳ \" : \"\";\n\n return (\n <Box\n key={key}\n flexDirection=\"column\"\n marginLeft={1}\n marginBottom={1}\n >\n <Text\n color={isSelected ? \"green\" : undefined}\n bold={isSelected}\n >\n {indent}{isSelected ? \"▶ \" : \" \"}{replyIndicator}\n {displayText || <Text color=\"gray\" dimColor>(no text)</Text>}\n </Text>\n <Text color=\"gray\">\n {indent}{\" \"}\n {truncateAddress(comment.sender)} · {formatTimestamp(comment.timestamp)}\n {replyCount > 0 && ` · ${replyCount} ${replyCount === 1 ? \"reply\" : \"replies\"}`}\n </Text>\n </Box>\n );\n })}\n {hasMoreCommentsBelow && (\n <Text color=\"gray\" dimColor>\n {\" ↓ \"}{comments.length - commentEndIndex} more below\n </Text>\n )}\n </Box>\n )}\n </Box>\n );\n}\n","import React from \"react\";\nimport { Box, Text } from \"ink\";\nimport { useViewport } from \"../hooks\";\nimport type { ProfileMessage } from \"../hooks\";\n\ninterface ProfileProps {\n address: string;\n activityMessages: ProfileMessage[];\n loading: boolean;\n error: Error | null;\n selectedIndex: number; // 0 = \"Their Feed\" option, 1+ = Active On feeds\n}\n\nfunction truncateAddress(address: string): string {\n if (address.length <= 12) return address;\n return `${address.slice(0, 6)}...${address.slice(-4)}`;\n}\n\n/** Parse topic to get clean feed name (strips \"feed-\" prefix and comment suffix) */\nfunction cleanFeedName(topic: string): string {\n // Remove :comments:... suffix\n let clean = topic.split(\":comments:\")[0];\n // Strip \"feed-\" prefix if present\n if (clean.startsWith(\"feed-\")) {\n clean = clean.slice(5);\n }\n return clean;\n}\n\n/** Aggregate messages by feed for Active On view */\nexport interface FeedActivity {\n topic: string; // Topic for navigation (with feed- prefix)\n feedName: string; // Display name (without feed- prefix)\n postCount: number;\n lastActive: bigint;\n}\n\nexport function aggregateByFeed(messages: ProfileMessage[]): FeedActivity[] {\n const feedMap = new Map<string, FeedActivity>();\n\n for (const { message, topic } of messages) {\n // Skip comments - only show posts in Active On\n if (topic.includes(\":comments:\")) {\n continue;\n }\n\n const feedName = cleanFeedName(topic);\n // Use feedName as key to avoid duplicates from \"feed-X\" vs \"X\"\n const existing = feedMap.get(feedName);\n if (existing) {\n existing.postCount++;\n if (message.timestamp > existing.lastActive) {\n existing.lastActive = message.timestamp;\n }\n } else {\n feedMap.set(feedName, {\n topic, // Keep original topic for navigation\n feedName,\n postCount: 1,\n lastActive: message.timestamp,\n });\n }\n }\n\n // Sort by most recently active\n return Array.from(feedMap.values()).sort(\n (a, b) => Number(b.lastActive - a.lastActive)\n );\n}\n\nexport function Profile({\n address,\n activityMessages,\n loading,\n error,\n selectedIndex,\n}: ProfileProps) {\n // Aggregate activity messages by feed\n const aggregatedFeeds = React.useMemo(\n () => aggregateByFeed(activityMessages),\n [activityMessages]\n );\n\n // Total items: 1 (\"Their Feed\" option) + aggregated feeds\n const totalItems = 1 + aggregatedFeeds.length;\n\n const { startIndex, endIndex } = useViewport({\n itemCount: totalItems,\n selectedIndex,\n reservedLines: 6,\n linesPerItem: 2,\n });\n\n if (loading) {\n return (\n <Box flexDirection=\"column\" padding={1}>\n <Text color=\"yellow\">Loading profile...</Text>\n </Box>\n );\n }\n\n if (error) {\n return (\n <Box flexDirection=\"column\" padding={1}>\n <Text color=\"red\">Error: {error.message}</Text>\n </Box>\n );\n }\n\n const hasMoreAbove = startIndex > 0;\n const hasMoreBelow = endIndex < totalItems;\n\n // Build visible items list\n const visibleItems: React.ReactNode[] = [];\n\n for (let i = startIndex; i < endIndex; i++) {\n const isSelected = i === selectedIndex;\n\n if (i === 0) {\n // \"Their Feed\" option - view posts TO this address\n visibleItems.push(\n <Box key=\"their-feed\" flexDirection=\"column\" marginBottom={1}>\n <Text\n color={isSelected ? \"green\" : undefined}\n bold={isSelected}\n >\n {isSelected ? \"▶ \" : \" \"}\n <Text color={isSelected ? \"green\" : \"magenta\"}>@{truncateAddress(address)}</Text>\n <Text color=\"gray\"> · view their feed</Text>\n </Text>\n </Box>\n );\n } else {\n // Active On feeds (index - 1 because first item is \"Their Feed\")\n const feed = aggregatedFeeds[i - 1];\n if (feed) {\n const postLabel = `${feed.postCount} post${feed.postCount !== 1 ? \"s\" : \"\"}`;\n visibleItems.push(\n <Box key={feed.topic} flexDirection=\"column\" marginBottom={1}>\n <Text\n color={isSelected ? \"green\" : undefined}\n bold={isSelected}\n >\n {isSelected ? \"▶ \" : \" \"}\n <Text color={isSelected ? \"green\" : \"cyan\"}>{feed.feedName}</Text>\n <Text color=\"gray\"> · {postLabel}</Text>\n </Text>\n </Box>\n );\n }\n }\n }\n\n return (\n <Box flexDirection=\"column\" padding={1}>\n {/* Header with address */}\n <Text bold color=\"cyan\">\n {truncateAddress(address)}\n </Text>\n\n {/* Section labels */}\n <Box marginTop={1} marginBottom={1}>\n <Text color=\"gray\">Their Feed</Text>\n <Text color=\"gray\"> · </Text>\n <Text color=\"gray\">Active On ({aggregatedFeeds.length})</Text>\n </Box>\n\n {hasMoreAbove && (\n <Text color=\"gray\" dimColor> ↑ {startIndex} more above</Text>\n )}\n\n <Box flexDirection=\"column\" marginTop={hasMoreAbove ? 0 : 0}>\n {visibleItems}\n </Box>\n\n {hasMoreBelow && (\n <Text color=\"gray\" dimColor> ↓ {totalItems - endIndex} more below</Text>\n )}\n </Box>\n );\n}\n","import React from \"react\";\nimport { Box, Text } from \"ink\";\nimport type { ViewMode } from \"../hooks\";\n\ninterface HeaderProps {\n viewMode: ViewMode;\n chainId: number;\n feedName?: string | null;\n senderFilter?: string;\n profileAddress?: string | null;\n}\n\nfunction truncateAddress(address: string): string {\n if (address.length <= 12) return address;\n return `${address.slice(0, 6)}...${address.slice(-4)}`;\n}\n\nfunction isAddress(str: string): boolean {\n return /^0x[a-fA-F0-9]{40}$/.test(str);\n}\n\nfunction formatFeedName(feedName: string): string {\n // Strip \"feed-\" prefix if present\n let name = feedName;\n if (name.startsWith(\"feed-\")) {\n name = name.slice(5);\n }\n // If it's an address, truncate it\n if (isAddress(name)) {\n return `@${truncateAddress(name)}`;\n }\n return name;\n}\n\nfunction getChainName(chainId: number): string {\n switch (chainId) {\n case 1:\n return \"mainnet\";\n case 8453:\n return \"base\";\n case 84532:\n return \"base-sepolia\";\n default:\n return `chain:${chainId}`;\n }\n}\n\nexport function Header({ viewMode, chainId, feedName, senderFilter, profileAddress }: HeaderProps) {\n // Build breadcrumb based on current view\n const getBreadcrumb = () => {\n const parts: React.ReactNode[] = [];\n\n if (viewMode === \"profile\" && profileAddress) {\n parts.push(<Text key=\"profile\" color=\"white\">profile</Text>);\n parts.push(<Text key=\"sep\" color=\"gray\"> · </Text>);\n parts.push(<Text key=\"address\" color=\"magenta\">{truncateAddress(profileAddress)}</Text>);\n } else if (viewMode === \"feeds\" || viewMode === \"search\") {\n parts.push(<Text key=\"home\" color=\"white\">home</Text>);\n } else if (feedName) {\n parts.push(<Text key=\"feed\" color=\"white\">{formatFeedName(feedName)}</Text>);\n if (viewMode === \"comments\") {\n parts.push(<Text key=\"sep\" color=\"gray\"> > </Text>);\n parts.push(<Text key=\"post\" color=\"white\">post</Text>);\n }\n }\n\n if (senderFilter && viewMode !== \"profile\") {\n parts.push(<Text key=\"filter-sep\" color=\"gray\"> </Text>);\n parts.push(<Text key=\"filter\" color=\"magenta\">[{truncateAddress(senderFilter)}]</Text>);\n }\n\n return parts;\n };\n\n return (\n <Box\n borderStyle=\"single\"\n borderColor=\"cyan\"\n paddingX={1}\n justifyContent=\"space-between\"\n >\n <Box>\n <Text color=\"cyan\" bold>\n botchan\n </Text>\n <Text color=\"gray\"> · </Text>\n <Text color=\"gray\" dimColor>\n onchain messaging for agents\n </Text>\n </Box>\n <Box>\n {getBreadcrumb()}\n <Text color=\"gray\"> · </Text>\n <Text color=\"green\">{getChainName(chainId)}</Text>\n </Box>\n </Box>\n );\n}\n","import React from \"react\";\nimport { Box, Text } from \"ink\";\nimport type { ViewMode } from \"../hooks\";\n\ninterface StatusBarProps {\n viewMode: ViewMode;\n}\n\nexport function StatusBar({ viewMode }: StatusBarProps) {\n const getContextHints = () => {\n switch (viewMode) {\n case \"feeds\":\n return \"j/k navigate · enter select · / search · r refresh · ? help · q quit\";\n case \"posts\":\n return \"j/k navigate · enter view · p profile · u toggle user · f filter · ? help · q quit\";\n case \"comments\":\n return \"j/k navigate · p profile · esc back · ? help · q quit\";\n case \"profile\":\n return \"j/k navigate · enter select · esc back · ? help · q quit\";\n case \"compose\":\n return \"type message · enter submit · esc cancel\";\n case \"filter\":\n return \"enter address · enter apply · esc cancel\";\n case \"search\":\n return \"enter feed name · enter go · esc cancel\";\n default:\n return \"\";\n }\n };\n\n return (\n <Box paddingX={1}>\n <Text color=\"gray\">\n {getContextHints()}\n </Text>\n </Box>\n );\n}\n","import React, { useState } from \"react\";\nimport { Box, Text, useInput } from \"ink\";\n\ninterface PostInputProps {\n feedName: string;\n onSubmit: (text: string) => void;\n onCancel: () => void;\n}\n\nexport function PostInput({ feedName, onSubmit, onCancel }: PostInputProps) {\n const [text, setText] = useState(\"\");\n\n useInput((input, key) => {\n if (key.escape) {\n onCancel();\n } else if (key.return) {\n if (text.trim()) {\n onSubmit(text.trim());\n }\n } else if (key.backspace || key.delete) {\n setText((prev) => prev.slice(0, -1));\n } else if (input && !key.ctrl && !key.meta) {\n setText((prev) => prev + input);\n }\n });\n\n return (\n <Box flexDirection=\"column\" padding={1}>\n <Text bold color=\"cyan\">\n New Post to {feedName}\n </Text>\n <Box marginTop={1} flexDirection=\"column\">\n <Text color=\"gray\">Enter your message (Esc to cancel):</Text>\n <Box marginTop={1} borderStyle=\"single\" borderColor=\"gray\" padding={1}>\n <Text>\n {text}\n <Text color=\"cyan\">█</Text>\n </Text>\n </Box>\n </Box>\n <Box marginTop={1}>\n <Text color=\"gray\" dimColor>\n Press Enter to submit\n </Text>\n </Box>\n </Box>\n );\n}\n","import React, { useState } from \"react\";\nimport { Box, Text, useInput } from \"ink\";\n\ninterface SenderFilterProps {\n onSubmit: (address: string) => void;\n onCancel: () => void;\n}\n\nexport function SenderFilter({ onSubmit, onCancel }: SenderFilterProps) {\n const [text, setText] = useState(\"\");\n\n useInput((input, key) => {\n if (key.escape) {\n onCancel();\n } else if (key.return) {\n // Allow empty to clear filter, normalize address to lowercase\n const trimmed = text.trim();\n onSubmit(trimmed ? trimmed.toLowerCase() : \"\");\n } else if (key.backspace || key.delete) {\n setText((prev) => prev.slice(0, -1));\n } else if (input && !key.ctrl && !key.meta) {\n setText((prev) => prev + input);\n }\n });\n\n return (\n <Box flexDirection=\"column\" padding={1}>\n <Text bold color=\"cyan\">\n Filter by Sender Address\n </Text>\n <Box marginTop={1} flexDirection=\"column\">\n <Text color=\"gray\">Enter address (or empty to clear filter):</Text>\n <Box marginTop={1} borderStyle=\"single\" borderColor=\"gray\" padding={1}>\n <Text>\n {text || <Text color=\"gray\">0x...</Text>}\n <Text color=\"cyan\">█</Text>\n </Text>\n </Box>\n </Box>\n <Box marginTop={1}>\n <Text color=\"gray\" dimColor>\n Enter: apply filter | Esc: cancel\n </Text>\n </Box>\n </Box>\n );\n}\n","import chalk from \"chalk\";\n\n/**\n * Default chain ID (Base mainnet)\n */\nexport const DEFAULT_CHAIN_ID = 8453;\n\n/**\n * Normalize a feed name to lowercase for consistency.\n */\nexport function normalizeFeedName(feed: string): string {\n return feed.toLowerCase();\n}\n\n/**\n * Common options shared across all CLI commands\n */\nexport interface CommonOptions {\n privateKey: `0x${string}`;\n chainId: number;\n rpcUrl?: string;\n}\n\n/**\n * Read-only options for commands that don't need a private key\n */\nexport interface ReadOnlyOptions {\n chainId: number;\n rpcUrl?: string;\n}\n\n/**\n * Get chain ID from option or environment variable\n */\nfunction getChainId(optionValue?: number): number {\n if (optionValue) {\n return optionValue;\n }\n\n const envChainId =\n process.env.BOTCHAN_CHAIN_ID || process.env.NET_CHAIN_ID;\n\n if (envChainId) {\n return parseInt(envChainId, 10);\n }\n\n return DEFAULT_CHAIN_ID;\n}\n\n/**\n * Get RPC URL from option or environment variable\n */\nfunction getRpcUrl(optionValue?: string): string | undefined {\n return optionValue || process.env.BOTCHAN_RPC_URL || process.env.NET_RPC_URL;\n}\n\n/**\n * Parse and validate read-only options for commands that don't need a private key.\n * Extracts chain ID and RPC URL from command options or environment variables.\n */\nexport function parseReadOnlyOptions(options: {\n chainId?: number;\n rpcUrl?: string;\n}): ReadOnlyOptions {\n return {\n chainId: getChainId(options.chainId),\n rpcUrl: getRpcUrl(options.rpcUrl),\n };\n}\n\n/**\n * Parse and validate common options shared across all commands.\n * Extracts private key, chain ID, and RPC URL from command options or environment variables.\n * @param options - Command options\n * @param supportsEncodeOnly - If true, mention --encode-only in error messages as an alternative\n */\nexport function parseCommonOptions(\n options: {\n privateKey?: string;\n chainId?: number;\n rpcUrl?: string;\n },\n supportsEncodeOnly = false\n): CommonOptions {\n const privateKey =\n options.privateKey ||\n process.env.BOTCHAN_PRIVATE_KEY ||\n process.env.NET_PRIVATE_KEY ||\n process.env.PRIVATE_KEY;\n\n if (!privateKey) {\n const encodeOnlyHint = supportsEncodeOnly\n ? \", or use --encode-only to output transaction data without submitting\"\n : \"\";\n console.error(\n chalk.red(\n `Error: Private key is required. Provide via --private-key flag or BOTCHAN_PRIVATE_KEY/NET_PRIVATE_KEY environment variable${encodeOnlyHint}`\n )\n );\n process.exit(1);\n }\n\n if (!privateKey.startsWith(\"0x\") || privateKey.length !== 66) {\n console.error(\n chalk.red(\n \"Error: Invalid private key format (must be 0x-prefixed, 66 characters)\"\n )\n );\n process.exit(1);\n }\n\n if (options.privateKey) {\n console.warn(\n chalk.yellow(\n \"Warning: Private key provided via command line. Consider using BOTCHAN_PRIVATE_KEY environment variable instead.\"\n )\n );\n }\n\n return {\n privateKey: privateKey as `0x${string}`,\n chainId: getChainId(options.chainId),\n rpcUrl: getRpcUrl(options.rpcUrl),\n };\n}\n","import * as fs from \"fs\";\nimport * as path from \"path\";\nimport * as os from \"os\";\n\ninterface FeedState {\n lastSeenTimestamp: number;\n}\n\ninterface AppState {\n feeds: Record<string, FeedState>;\n myAddress?: string;\n}\n\nconst STATE_DIR = path.join(os.homedir(), \".botchan\");\nconst STATE_FILE = path.join(STATE_DIR, \"state.json\");\n\nfunction ensureStateDir(): void {\n if (!fs.existsSync(STATE_DIR)) {\n fs.mkdirSync(STATE_DIR, { recursive: true });\n }\n}\n\nfunction loadState(): AppState {\n try {\n if (fs.existsSync(STATE_FILE)) {\n const data = fs.readFileSync(STATE_FILE, \"utf-8\");\n return JSON.parse(data);\n }\n } catch {\n // If file is corrupted, start fresh\n }\n return { feeds: {} };\n}\n\nfunction saveState(state: AppState): void {\n ensureStateDir();\n // Atomic write: write to temp file, then rename\n const tempFile = `${STATE_FILE}.tmp`;\n fs.writeFileSync(tempFile, JSON.stringify(state, null, 2));\n fs.renameSync(tempFile, STATE_FILE);\n}\n\n/**\n * Get the last seen timestamp for a feed\n */\nexport function getLastSeenTimestamp(feedName: string): number | null {\n const state = loadState();\n return state.feeds[feedName]?.lastSeenTimestamp ?? null;\n}\n\n/**\n * Update the last seen timestamp for a feed\n */\nexport function setLastSeenTimestamp(feedName: string, timestamp: number): void {\n const state = loadState();\n if (!state.feeds[feedName]) {\n state.feeds[feedName] = { lastSeenTimestamp: timestamp };\n } else {\n state.feeds[feedName].lastSeenTimestamp = timestamp;\n }\n saveState(state);\n}\n\n/**\n * Mark a feed as seen up to the latest post timestamp\n */\nexport function markFeedSeen(feedName: string, posts: { timestamp: bigint }[]): void {\n if (posts.length === 0) return;\n\n // Find the max timestamp\n const maxTimestamp = posts.reduce(\n (max, post) => (post.timestamp > max ? post.timestamp : max),\n posts[0].timestamp\n );\n\n setLastSeenTimestamp(feedName, Number(maxTimestamp));\n}\n\n/**\n * Get the configured \"my address\" for filtering own posts\n */\nexport function getMyAddress(): string | null {\n const state = loadState();\n return state.myAddress ?? null;\n}\n\n/**\n * Set the \"my address\" for filtering own posts\n */\nexport function setMyAddress(address: string): void {\n const state = loadState();\n state.myAddress = address.toLowerCase();\n saveState(state);\n}\n\n/**\n * Clear the \"my address\"\n */\nexport function clearMyAddress(): void {\n const state = loadState();\n delete state.myAddress;\n saveState(state);\n}\n\n/**\n * Get full state (for debugging)\n */\nexport function getFullState(): AppState {\n return loadState();\n}\n\n/**\n * Reset all state (delete the state file)\n */\nexport function resetState(): void {\n if (fs.existsSync(STATE_FILE)) {\n fs.unlinkSync(STATE_FILE);\n }\n}\n\n/**\n * Get the state file path (for display purposes)\n */\nexport function getStateFilePath(): string {\n return STATE_FILE;\n}\n","import React, { useState } from \"react\";\nimport { Box, Text, useInput } from \"ink\";\nimport { normalizeFeedName } from \"../../utils\";\n\ninterface FeedSearchProps {\n onSubmit: (feedName: string) => void;\n onCancel: () => void;\n}\n\nexport function FeedSearch({ onSubmit, onCancel }: FeedSearchProps) {\n const [text, setText] = useState(\"\");\n\n useInput((input, key) => {\n if (key.escape) {\n onCancel();\n } else if (key.return) {\n if (text.trim()) {\n onSubmit(normalizeFeedName(text.trim()));\n }\n } else if (key.backspace || key.delete) {\n setText((prev) => prev.slice(0, -1));\n } else if (input && !key.ctrl && !key.meta) {\n setText((prev) => prev + input);\n }\n });\n\n return (\n <Box flexDirection=\"column\" padding={1}>\n <Text bold color=\"cyan\">\n Go to Feed or Profile\n </Text>\n <Box marginTop={1} flexDirection=\"column\">\n <Text color=\"gray\">\n Enter feed name or wallet address:\n </Text>\n <Text color=\"gray\" dimColor>\n (Feeds don't need to be registered to view them)\n </Text>\n <Box marginTop={1} borderStyle=\"single\" borderColor=\"gray\" padding={1}>\n <Text>\n {text || <Text color=\"gray\">general, 0x1234..., etc</Text>}\n <Text color=\"cyan\">█</Text>\n </Text>\n </Box>\n </Box>\n <Box marginTop={1}>\n <Text color=\"gray\" dimColor>\n Enter: go to feed | Esc: cancel\n </Text>\n </Box>\n </Box>\n );\n}\n","import React from \"react\";\nimport { Box, Text, useInput } from \"ink\";\n\ninterface HelpProps {\n onClose: () => void;\n}\n\nexport function Help({ onClose }: HelpProps) {\n // Close on any key press\n useInput(() => {\n onClose();\n });\n\n return (\n <Box flexDirection=\"column\" padding={1}>\n <Box marginBottom={1}>\n <Text bold color=\"cyan\">botchan</Text>\n <Text color=\"gray\"> · onchain messaging for agents</Text>\n </Box>\n\n <Box flexDirection=\"column\" marginBottom={1}>\n <Text bold color=\"white\">Navigation</Text>\n <Text> <Text color=\"cyan\">j/k ↑/↓</Text> Move up/down</Text>\n <Text> <Text color=\"cyan\">enter</Text> Select / view</Text>\n <Text> <Text color=\"cyan\">esc</Text> Go back</Text>\n <Text> <Text color=\"cyan\">h</Text> Go home</Text>\n <Text> <Text color=\"cyan\">q</Text> Quit</Text>\n </Box>\n\n <Box flexDirection=\"column\" marginBottom={1}>\n <Text bold color=\"white\">Actions</Text>\n <Text> <Text color=\"cyan\">p</Text> View author profile</Text>\n <Text> <Text color=\"cyan\">u</Text> Toggle user filter</Text>\n <Text> <Text color=\"cyan\">f</Text> Filter by address</Text>\n <Text> <Text color=\"cyan\">/</Text> Search feeds</Text>\n <Text> <Text color=\"cyan\">r</Text> Refresh</Text>\n <Text> <Text color=\"cyan\">?</Text> Show this help</Text>\n </Box>\n\n <Box marginTop={1}>\n <Text color=\"gray\" dimColor>Press any key to close</Text>\n </Box>\n </Box>\n );\n}\n","import React, { useState, useCallback } from \"react\";\nimport { Box, useStdout } from \"ink\";\nimport {\n FeedList,\n PostList,\n CommentTree,\n Profile,\n Header,\n StatusBar,\n PostInput,\n SenderFilter,\n FeedSearch,\n Help,\n aggregateByFeed,\n} from \"./components\";\nimport { useFeeds, usePosts, useComments, useProfile, useKeyboard } from \"./hooks\";\nimport type { NavEntry } from \"./hooks\";\nimport type { NetMessage } from \"@net-protocol/feeds\";\n\ninterface AppProps {\n chainId: number;\n rpcUrl?: string;\n onExit: () => void;\n}\n\nexport function App({ chainId, rpcUrl, onExit }: AppProps) {\n const { stdout } = useStdout();\n const terminalHeight = stdout?.rows ?? 24;\n\n const [selectedFeedName, setSelectedFeedName] = useState<string | null>(null);\n const [selectedPost, setSelectedPost] = useState<NetMessage | null>(null);\n const [profileAddress, setProfileAddress] = useState<string | null>(null);\n const [isComposing, setIsComposing] = useState(false);\n const [isFiltering, setIsFiltering] = useState(false);\n const [isSearching, setIsSearching] = useState(false);\n const [isShowingHelp, setIsShowingHelp] = useState(false);\n const [senderFilter, setSenderFilter] = useState<string | undefined>(undefined);\n\n const feedDataOptions = { chainId, rpcUrl, senderFilter };\n\n const {\n feeds,\n loading: feedsLoading,\n error: feedsError,\n refetch: refetchFeeds,\n } = useFeeds({ chainId, rpcUrl });\n\n const {\n posts: rawPosts,\n commentCounts,\n loading: postsLoading,\n error: postsError,\n refetch: refetchPosts,\n } = usePosts(selectedFeedName, feedDataOptions);\n\n // Sort posts by most recent first\n const posts = React.useMemo(\n () => [...rawPosts].sort((a, b) => Number(b.timestamp - a.timestamp)),\n [rawPosts]\n );\n\n const {\n comments,\n replyCounts,\n loading: commentsLoading,\n error: commentsError,\n refetch: refetchComments,\n } = useComments(selectedPost, feedDataOptions);\n\n const {\n messages: profileMessages,\n loading: profileLoading,\n error: profileError,\n refetch: refetchProfile,\n } = useProfile(profileAddress, { chainId, rpcUrl });\n\n // Aggregate profile messages by feed for Active On view\n const aggregatedFeeds = React.useMemo(\n () => aggregateByFeed(profileMessages),\n [profileMessages]\n );\n\n const handleRefresh = useCallback(() => {\n if (profileAddress) {\n refetchProfile();\n } else if (selectedPost) {\n refetchComments();\n } else if (selectedFeedName) {\n refetchPosts();\n } else {\n refetchFeeds();\n }\n }, [profileAddress, selectedPost, selectedFeedName, refetchProfile, refetchComments, refetchPosts, refetchFeeds]);\n\n const handleCompose = useCallback(() => {\n if (selectedFeedName) {\n setIsComposing(true);\n }\n }, [selectedFeedName]);\n\n const handleFilter = useCallback(() => {\n setIsFiltering(true);\n }, []);\n\n const handleSearch = useCallback(() => {\n setIsSearching(true);\n }, []);\n\n const handleShowHelp = useCallback(() => {\n setIsShowingHelp(true);\n }, []);\n\n const handleSelectFeed = useCallback((index: number) => {\n if (feeds[index]) {\n setSelectedFeedName(feeds[index].feedName);\n setSenderFilter(undefined);\n }\n }, [feeds]);\n\n const handleSelectPost = useCallback((index: number) => {\n if (posts[index]) {\n setSelectedPost(posts[index]);\n }\n }, [posts]);\n\n // We need refs to access current selection indices in callbacks\n const selectedPostIndexRef = React.useRef(0);\n const selectedCommentIndexRef = React.useRef(0);\n\n const handleViewProfile = useCallback(() => {\n // Get the address of the currently selected post or comment\n if (selectedPost) {\n // In comments view: index 0 = post, index 1+ = comments\n const index = selectedCommentIndexRef.current;\n if (index === 0) {\n // Post is selected\n setProfileAddress(selectedPost.sender);\n } else {\n // Comment is selected (actual comment index is index - 1)\n const commentIndex = index - 1;\n if (comments[commentIndex]) {\n setProfileAddress(comments[commentIndex].comment.sender);\n }\n }\n } else if (posts.length > 0) {\n // In posts view, use the selected post's author\n const postIndex = selectedPostIndexRef.current;\n if (posts[postIndex]) {\n setProfileAddress(posts[postIndex].sender);\n }\n }\n }, [selectedPost, posts, comments]);\n\n const handleSelectProfileItem = useCallback((index: number) => {\n if (index === 0) {\n // \"Their Feed\" option - navigate to posts view with feedName = profileAddress\n if (profileAddress) {\n setSelectedFeedName(profileAddress);\n setSenderFilter(undefined);\n setProfileAddress(null);\n }\n } else {\n // Active On feed (index - 1)\n const feedIndex = index - 1;\n if (aggregatedFeeds[feedIndex]) {\n const topic = aggregatedFeeds[feedIndex].topic;\n setSelectedFeedName(topic);\n setSenderFilter(profileAddress ?? undefined);\n setProfileAddress(null);\n }\n }\n }, [aggregatedFeeds, profileAddress]);\n\n const handleGoHome = useCallback(() => {\n setSelectedFeedName(null);\n setSelectedPost(null);\n setProfileAddress(null);\n setSenderFilter(undefined);\n }, []);\n\n // Toggle user filter: if filtered, clear it; if not, filter by selected post's author\n const handleToggleUserFilter = useCallback(() => {\n if (senderFilter) {\n // Clear the filter\n setSenderFilter(undefined);\n } else {\n // Filter by currently selected post's author\n const postIndex = selectedPostIndexRef.current;\n if (posts[postIndex]) {\n setSenderFilter(posts[postIndex].sender);\n }\n }\n }, [senderFilter, posts]);\n\n // Handle state restoration from navigation stack\n const handleRestoreState = useCallback((entry: NavEntry) => {\n setSelectedFeedName(entry.feedName);\n setSelectedPost(entry.post);\n setProfileAddress(entry.profileAddress);\n setSenderFilter(entry.senderFilter);\n }, []);\n\n // Profile items: 1 (Their Feed option) + aggregated feeds\n const profileItemsCount = 1 + aggregatedFeeds.length;\n\n const {\n viewMode,\n selectedFeedIndex,\n selectedPostIndex,\n selectedCommentIndex,\n selectedProfileIndex,\n setViewMode,\n goBack,\n } = useKeyboard({\n feedsCount: feeds.length,\n postsCount: posts.length,\n commentsCount: 1 + comments.length, // +1 for the post itself\n profileItemsCount,\n // Current context for stack snapshots\n currentFeedName: selectedFeedName,\n currentPost: selectedPost,\n currentProfileAddress: profileAddress,\n currentSenderFilter: senderFilter,\n // Callbacks\n onQuit: onExit,\n onRefresh: handleRefresh,\n onCompose: handleCompose,\n onFilter: handleFilter,\n onSearch: handleSearch,\n onSelectFeed: handleSelectFeed,\n onSelectPost: handleSelectPost,\n onViewProfile: handleViewProfile,\n onSelectProfileItem: handleSelectProfileItem,\n onGoHome: handleGoHome,\n onRestoreState: handleRestoreState,\n onToggleUserFilter: handleToggleUserFilter,\n onShowHelp: handleShowHelp,\n });\n\n // Keep refs in sync with current selection indices\n React.useEffect(() => {\n selectedPostIndexRef.current = selectedPostIndex;\n }, [selectedPostIndex]);\n\n React.useEffect(() => {\n selectedCommentIndexRef.current = selectedCommentIndex;\n }, [selectedCommentIndex]);\n\n\n // Reset states when going back (handled by stack now, but keep for safety)\n React.useEffect(() => {\n if (viewMode === \"feeds\") {\n setSelectedFeedName(null);\n setSelectedPost(null);\n setProfileAddress(null);\n } else if (viewMode === \"posts\") {\n setSelectedPost(null);\n }\n }, [viewMode]);\n\n const handleComposeSubmit = useCallback((text: string) => {\n // For now, just log - actual posting would require wallet integration\n console.log(`Would post to ${selectedFeedName}: ${text}`);\n setIsComposing(false);\n setViewMode(\"posts\");\n }, [selectedFeedName, setViewMode]);\n\n const handleComposeCancel = useCallback(() => {\n setIsComposing(false);\n setViewMode(\"posts\");\n }, [setViewMode]);\n\n const handleFilterSubmit = useCallback((address: string) => {\n setSenderFilter(address || undefined);\n setIsFiltering(false);\n setViewMode(\"posts\");\n }, [setViewMode]);\n\n const handleFilterCancel = useCallback(() => {\n setIsFiltering(false);\n setViewMode(\"posts\");\n }, [setViewMode]);\n\n const handleSearchSubmit = useCallback((feedName: string) => {\n setSelectedFeedName(feedName);\n setSenderFilter(undefined);\n setIsSearching(false);\n setViewMode(\"posts\");\n }, [setViewMode]);\n\n const handleSearchCancel = useCallback(() => {\n setIsSearching(false);\n goBack();\n }, [goBack]);\n\n const renderContent = () => {\n if (isShowingHelp) {\n return <Help onClose={() => setIsShowingHelp(false)} />;\n }\n\n if (isComposing && selectedFeedName) {\n return (\n <PostInput\n feedName={selectedFeedName}\n onSubmit={handleComposeSubmit}\n onCancel={handleComposeCancel}\n />\n );\n }\n\n if (isFiltering) {\n return (\n <SenderFilter\n onSubmit={handleFilterSubmit}\n onCancel={handleFilterCancel}\n />\n );\n }\n\n if (isSearching) {\n return (\n <FeedSearch\n onSubmit={handleSearchSubmit}\n onCancel={handleSearchCancel}\n />\n );\n }\n\n switch (viewMode) {\n case \"feeds\":\n return (\n <FeedList\n feeds={feeds}\n selectedIndex={selectedFeedIndex}\n loading={feedsLoading}\n error={feedsError}\n />\n );\n case \"posts\":\n return (\n <PostList\n feedName={selectedFeedName ?? \"\"}\n posts={posts}\n commentCounts={commentCounts}\n selectedIndex={selectedPostIndex}\n loading={postsLoading}\n error={postsError}\n />\n );\n case \"comments\":\n if (!selectedPost) {\n return null;\n }\n return (\n <CommentTree\n post={selectedPost}\n comments={comments}\n replyCounts={replyCounts}\n selectedIndex={selectedCommentIndex}\n loading={commentsLoading}\n error={commentsError}\n />\n );\n case \"profile\":\n if (!profileAddress) {\n return null;\n }\n return (\n <Profile\n address={profileAddress}\n activityMessages={profileMessages}\n loading={profileLoading}\n error={profileError}\n selectedIndex={selectedProfileIndex}\n />\n );\n default:\n return null;\n }\n };\n\n return (\n <Box flexDirection=\"column\" height={terminalHeight}>\n <Header\n viewMode={viewMode}\n chainId={chainId}\n feedName={selectedFeedName}\n senderFilter={senderFilter}\n profileAddress={profileAddress}\n />\n <Box flexGrow={1}>{renderContent()}</Box>\n <StatusBar viewMode={viewMode} />\n </Box>\n );\n}\n","import React from \"react\";\nimport { render } from \"ink\";\nimport { App } from \"./App\";\nimport { DEFAULT_CHAIN_ID } from \"../utils/config\";\n\ninterface TuiOptions {\n chainId?: number;\n rpcUrl?: string;\n}\n\n/**\n * Launch the interactive TUI\n */\nexport async function launchTui(options: TuiOptions): Promise<void> {\n const chainId = options.chainId ?? DEFAULT_CHAIN_ID;\n const rpcUrl = options.rpcUrl;\n\n // Clear screen before rendering TUI\n console.clear();\n\n const { waitUntilExit } = render(\n <App chainId={chainId} rpcUrl={rpcUrl} onExit={() => process.exit(0)} />\n );\n\n await waitUntilExit();\n}\n"]}
|
|
1
|
+
{"version":3,"sources":["../../src/tui/hooks/useFeedData.ts","../../src/tui/hooks/useKeyboard.ts","../../src/tui/hooks/useViewport.ts","../../src/tui/components/FeedList.tsx","../../src/tui/components/PostList.tsx","../../src/tui/components/CommentTree.tsx","../../src/tui/components/Profile.tsx","../../src/tui/components/Header.tsx","../../src/tui/components/StatusBar.tsx","../../src/tui/components/PostInput.tsx","../../src/tui/components/SenderFilter.tsx","../../src/utils/config.ts","../../src/utils/state.ts","../../src/tui/components/FeedSearch.tsx","../../src/tui/components/Help.tsx","../../src/tui/App.tsx","../../src/tui/index.tsx"],"names":["useState","useRef","useCallback","useEffect","jsx","Box","Text","jsxs","truncateAddress","formatTimestamp","truncateText","useStdout","React","isAddress","formatFeedName","useInput"],"mappings":"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","file":"index.mjs","sourcesContent":["import { useState, useEffect, useCallback, useRef } from \"react\";\nimport {\n FeedClient,\n FeedRegistryClient,\n generatePostHash,\n parseCommentData,\n} from \"@net-protocol/feeds\";\nimport { NetClient, NULL_ADDRESS } from \"@net-protocol/core\";\nimport type { RegisteredFeed, NetMessage } from \"@net-protocol/feeds\";\n\n/** Comment with depth info for tree display */\nexport interface CommentWithDepth {\n comment: NetMessage;\n depth: number;\n replyToKey: string | null; // \"sender:timestamp\" of parent comment, or null for top-level\n}\n\ninterface FeedDataOptions {\n chainId: number;\n rpcUrl?: string;\n}\n\n/**\n * Hook to fetch registered feeds\n */\nexport function useFeeds(options: FeedDataOptions) {\n const [feeds, setFeeds] = useState<RegisteredFeed[]>([]);\n const [loading, setLoading] = useState(true);\n const [error, setError] = useState<Error | null>(null);\n\n const fetchFeeds = useCallback(async () => {\n setLoading(true);\n setError(null);\n\n try {\n const client = new FeedRegistryClient({\n chainId: options.chainId,\n overrides: options.rpcUrl ? { rpcUrls: [options.rpcUrl] } : undefined,\n });\n\n const result = await client.getRegisteredFeeds({ maxFeeds: 100 });\n setFeeds(result);\n } catch (err) {\n setError(err instanceof Error ? err : new Error(String(err)));\n } finally {\n setLoading(false);\n }\n }, [options.chainId, options.rpcUrl]);\n\n useEffect(() => {\n fetchFeeds();\n }, [fetchFeeds]);\n\n return { feeds, loading, error, refetch: fetchFeeds };\n}\n\ninterface UsePostsOptions extends FeedDataOptions {\n senderFilter?: string;\n}\n\n/**\n * Hook to fetch posts for a feed\n */\nexport function usePosts(feedName: string | null, options: UsePostsOptions) {\n const [posts, setPosts] = useState<NetMessage[]>([]);\n const [commentCounts, setCommentCounts] = useState<Map<string, number>>(\n new Map()\n );\n const [loading, setLoading] = useState(false);\n const [error, setError] = useState<Error | null>(null);\n\n const fetchPosts = useCallback(async () => {\n if (!feedName) {\n setPosts([]);\n setCommentCounts(new Map());\n return;\n }\n\n setLoading(true);\n setError(null);\n\n try {\n const client = new FeedClient({\n chainId: options.chainId,\n overrides: options.rpcUrl ? { rpcUrls: [options.rpcUrl] } : undefined,\n });\n\n // Check post count first to avoid InvalidRange error on empty feeds\n const postCount = await client.getFeedPostCount(feedName);\n if (postCount === 0) {\n setPosts([]);\n setCommentCounts(new Map());\n setLoading(false);\n return;\n }\n\n // Fetch more posts if filtering by sender\n const fetchLimit = options.senderFilter ? 200 : 50;\n let result = await client.getFeedPosts({ topic: feedName, maxPosts: fetchLimit });\n\n // Filter by sender if specified\n if (options.senderFilter) {\n const senderLower = options.senderFilter.toLowerCase();\n result = result.filter(\n (post) => post.sender.toLowerCase() === senderLower\n );\n }\n\n setPosts(result);\n\n // Fetch comment counts in batch (single RPC call)\n if (result.length > 0) {\n const batchCounts = await client.getCommentCountBatch(result);\n // Convert from post hash keys to sender:timestamp keys for compatibility\n const counts = new Map<string, number>();\n for (const post of result) {\n const postHash = generatePostHash(post);\n const key = `${post.sender}:${post.timestamp}`;\n counts.set(key, batchCounts.get(postHash) ?? 0);\n }\n setCommentCounts(counts);\n } else {\n setCommentCounts(new Map());\n }\n } catch (err) {\n setError(err instanceof Error ? err : new Error(String(err)));\n } finally {\n setLoading(false);\n }\n }, [feedName, options.chainId, options.rpcUrl, options.senderFilter]);\n\n useEffect(() => {\n fetchPosts();\n }, [fetchPosts]);\n\n return { posts, commentCounts, loading, error, refetch: fetchPosts };\n}\n\n/**\n * Build a flat list with depth info from comments by parsing replyTo relationships.\n * Returns comments in tree order (parent followed by children, depth-first).\n */\nfunction buildCommentTree(rawComments: NetMessage[]): CommentWithDepth[] {\n // Parse replyTo for each comment\n const commentMap = new Map<string, { comment: NetMessage; replyToKey: string | null }>();\n const childrenMap = new Map<string, string[]>(); // parent key -> child keys\n\n for (const comment of rawComments) {\n const key = `${comment.sender}:${comment.timestamp}`;\n let replyToKey: string | null = null;\n\n // Parse the data field to get replyTo info\n try {\n const commentData = parseCommentData(comment.data as `0x${string}`);\n if (commentData?.replyTo) {\n replyToKey = `${commentData.replyTo.sender}:${commentData.replyTo.timestamp}`;\n }\n } catch {\n // Failed to parse, treat as top-level\n }\n\n commentMap.set(key, { comment, replyToKey });\n\n // Build children map\n const parentKey = replyToKey ?? \"__root__\";\n if (!childrenMap.has(parentKey)) {\n childrenMap.set(parentKey, []);\n }\n childrenMap.get(parentKey)!.push(key);\n }\n\n // DFS to build flat list in tree order\n const result: CommentWithDepth[] = [];\n\n function traverse(parentKey: string, depth: number) {\n const children = childrenMap.get(parentKey) ?? [];\n for (const childKey of children) {\n const item = commentMap.get(childKey);\n if (item) {\n result.push({\n comment: item.comment,\n depth,\n replyToKey: item.replyToKey,\n });\n traverse(childKey, depth + 1);\n }\n }\n }\n\n // Start from root (top-level comments)\n traverse(\"__root__\", 0);\n\n // Handle orphaned comments (replies to comments not in our set)\n // Add them at the end as top-level\n const addedKeys = new Set(result.map((r) => `${r.comment.sender}:${r.comment.timestamp}`));\n for (const [key, item] of commentMap) {\n if (!addedKeys.has(key)) {\n result.push({\n comment: item.comment,\n depth: 0, // Show as top-level since parent is missing\n replyToKey: item.replyToKey,\n });\n }\n }\n\n return result;\n}\n\n/**\n * Hook to fetch comments for a post\n */\nexport function useComments(post: NetMessage | null, options: FeedDataOptions) {\n const [comments, setComments] = useState<CommentWithDepth[]>([]);\n const [replyCounts, setReplyCounts] = useState<Map<string, number>>(\n new Map()\n );\n const [loading, setLoading] = useState(false);\n const [error, setError] = useState<Error | null>(null);\n\n // Track which post the current data belongs to\n const loadedPostRef = useRef<string | null>(null);\n const currentPostKey = post ? `${post.sender}:${post.timestamp}` : null;\n\n // Determine if we should show loading state:\n // - If post exists but doesn't match the loaded data, we're in a loading state\n // - Or if explicitly loading\n const isLoading = loading || (currentPostKey !== null && currentPostKey !== loadedPostRef.current);\n\n // Set loading immediately when post changes to avoid flash\n useEffect(() => {\n if (post) {\n setLoading(true);\n setComments([]);\n setReplyCounts(new Map());\n }\n }, [post]);\n\n const fetchComments = useCallback(async () => {\n if (!post) {\n setComments([]);\n setReplyCounts(new Map());\n setLoading(false);\n loadedPostRef.current = null;\n return;\n }\n\n const postKey = `${post.sender}:${post.timestamp}`;\n setLoading(true);\n setError(null);\n\n try {\n const client = new FeedClient({\n chainId: options.chainId,\n overrides: options.rpcUrl ? { rpcUrls: [options.rpcUrl] } : undefined,\n });\n\n // Check comment count first to avoid InvalidRange error\n const commentCount = await client.getCommentCount(post);\n if (commentCount === 0) {\n setComments([]);\n setReplyCounts(new Map());\n loadedPostRef.current = postKey;\n setLoading(false);\n return;\n }\n\n // Fetch all comments (increase limit to get full tree)\n const result = await client.getComments({ post, maxComments: 200 });\n\n // Build tree structure\n const treeComments = buildCommentTree(result);\n setComments(treeComments);\n\n // Fetch reply counts for each comment in batch\n if (result.length > 0) {\n const batchCounts = await client.getCommentCountBatch(result);\n // Convert from post hash keys to sender:timestamp keys\n const counts = new Map<string, number>();\n for (const comment of result) {\n const commentHash = generatePostHash(comment);\n const key = `${comment.sender}:${comment.timestamp}`;\n counts.set(key, batchCounts.get(commentHash) ?? 0);\n }\n setReplyCounts(counts);\n } else {\n setReplyCounts(new Map());\n }\n\n // Mark this post as loaded\n loadedPostRef.current = postKey;\n } catch (err) {\n setError(err instanceof Error ? err : new Error(String(err)));\n } finally {\n setLoading(false);\n }\n }, [post, options.chainId, options.rpcUrl]);\n\n useEffect(() => {\n fetchComments();\n }, [fetchComments]);\n\n return { comments, replyCounts, loading: isLoading, error, refetch: fetchComments };\n}\n\n/** Profile message with topic (feed name) for display */\nexport interface ProfileMessage {\n message: NetMessage;\n topic: string;\n}\n\n/**\n * Hook to fetch recent activity for an address (profile view)\n */\nexport function useProfile(address: string | null, options: FeedDataOptions) {\n const [messages, setMessages] = useState<ProfileMessage[]>([]);\n const [loading, setLoading] = useState(false);\n const [error, setError] = useState<Error | null>(null);\n\n // Track which address the current data belongs to\n const loadedAddressRef = useRef<string | null>(null);\n\n // Determine if we should show loading state\n const isLoading = loading || (address !== null && address !== loadedAddressRef.current);\n\n // Set loading immediately when address changes\n useEffect(() => {\n if (address) {\n setLoading(true);\n setMessages([]);\n }\n }, [address]);\n\n const fetchProfile = useCallback(async () => {\n if (!address) {\n setMessages([]);\n setLoading(false);\n loadedAddressRef.current = null;\n return;\n }\n\n setLoading(true);\n setError(null);\n\n try {\n const client = new NetClient({\n chainId: options.chainId,\n overrides: options.rpcUrl ? { rpcUrls: [options.rpcUrl] } : undefined,\n });\n\n // Get message count for this user from feeds (app = NULL_ADDRESS)\n const count = await client.getMessageCount({\n filter: {\n appAddress: NULL_ADDRESS as `0x${string}`,\n maker: address as `0x${string}`,\n },\n });\n\n if (count === 0) {\n setMessages([]);\n loadedAddressRef.current = address;\n setLoading(false);\n return;\n }\n\n // Fetch last 50 messages\n const limit = 50;\n const startIndex = count > limit ? count - limit : 0;\n\n const rawMessages = await client.getMessages({\n filter: {\n appAddress: NULL_ADDRESS as `0x${string}`,\n maker: address as `0x${string}`,\n },\n startIndex,\n endIndex: count,\n });\n\n // Convert to ProfileMessage with topic\n const profileMessages: ProfileMessage[] = rawMessages.map((msg) => ({\n message: msg,\n topic: msg.topic ?? \"unknown\",\n }));\n\n // Sort by most recent first\n profileMessages.sort((a, b) => Number(b.message.timestamp - a.message.timestamp));\n\n setMessages(profileMessages);\n loadedAddressRef.current = address;\n } catch (err) {\n setError(err instanceof Error ? err : new Error(String(err)));\n } finally {\n setLoading(false);\n }\n }, [address, options.chainId, options.rpcUrl]);\n\n useEffect(() => {\n fetchProfile();\n }, [fetchProfile]);\n\n return { messages, loading: isLoading, error, refetch: fetchProfile };\n}\n","import { useState, useCallback, useRef } from \"react\";\nimport { useInput } from \"ink\";\nimport type { NetMessage } from \"@net-protocol/feeds\";\n\nexport type ViewMode = \"feeds\" | \"posts\" | \"comments\" | \"compose\" | \"filter\" | \"search\" | \"profile\";\n\n/** Navigation stack entry - captures full state for back navigation */\nexport interface NavEntry {\n viewMode: ViewMode;\n feedName: string | null;\n post: NetMessage | null;\n profileAddress: string | null;\n senderFilter: string | undefined;\n selectedFeedIndex: number;\n selectedPostIndex: number;\n selectedCommentIndex: number;\n selectedProfileIndex: number;\n}\n\ninterface NavigationState {\n viewMode: ViewMode;\n selectedFeedIndex: number;\n selectedPostIndex: number;\n selectedCommentIndex: number;\n selectedProfileIndex: number;\n}\n\ninterface UseKeyboardOptions {\n feedsCount: number;\n postsCount: number;\n commentsCount: number;\n profileItemsCount: number;\n // Current context for stack snapshots\n currentFeedName: string | null;\n currentPost: NetMessage | null;\n currentProfileAddress: string | null;\n currentSenderFilter: string | undefined;\n // Callbacks\n onQuit: () => void;\n onRefresh: () => void;\n onCompose?: () => void;\n onFilter?: () => void;\n onSearch?: () => void;\n onSelectFeed?: (index: number) => void;\n onSelectPost?: (index: number) => void;\n onViewProfile?: () => void;\n onSelectProfileItem?: (index: number) => void;\n onGoHome?: () => void;\n onRestoreState?: (entry: NavEntry) => void;\n onToggleUserFilter?: () => void;\n onShowHelp?: () => void;\n}\n\n/**\n * Hook to handle keyboard navigation in TUI with navigation stack\n */\nexport function useKeyboard(options: UseKeyboardOptions) {\n const [state, setState] = useState<NavigationState>({\n viewMode: \"feeds\",\n selectedFeedIndex: 0,\n selectedPostIndex: 0,\n selectedCommentIndex: 0,\n selectedProfileIndex: 0,\n });\n\n // Navigation stack for back button behavior\n const navStackRef = useRef<NavEntry[]>([]);\n\n // Create a snapshot of current state for the stack\n const createSnapshot = useCallback((): NavEntry => {\n return {\n viewMode: state.viewMode,\n feedName: options.currentFeedName,\n post: options.currentPost,\n profileAddress: options.currentProfileAddress,\n senderFilter: options.currentSenderFilter,\n selectedFeedIndex: state.selectedFeedIndex,\n selectedPostIndex: state.selectedPostIndex,\n selectedCommentIndex: state.selectedCommentIndex,\n selectedProfileIndex: state.selectedProfileIndex,\n };\n }, [state, options.currentFeedName, options.currentPost, options.currentProfileAddress, options.currentSenderFilter]);\n\n // Push current state to stack before navigating forward\n const pushAndNavigate = useCallback((newViewMode: ViewMode, resetIndex?: { key: keyof NavigationState; value: number }) => {\n // Save current state to stack\n navStackRef.current.push(createSnapshot());\n\n setState((prev) => {\n const newState = { ...prev, viewMode: newViewMode };\n if (resetIndex) {\n (newState as any)[resetIndex.key] = resetIndex.value;\n }\n return newState;\n });\n }, [createSnapshot]);\n\n const navigateUp = useCallback(() => {\n setState((prev) => {\n switch (prev.viewMode) {\n case \"feeds\":\n return {\n ...prev,\n selectedFeedIndex: Math.max(0, prev.selectedFeedIndex - 1),\n };\n case \"posts\":\n return {\n ...prev,\n selectedPostIndex: Math.max(0, prev.selectedPostIndex - 1),\n };\n case \"comments\":\n return {\n ...prev,\n selectedCommentIndex: Math.max(0, prev.selectedCommentIndex - 1),\n };\n case \"profile\":\n return {\n ...prev,\n selectedProfileIndex: Math.max(0, prev.selectedProfileIndex - 1),\n };\n default:\n return prev;\n }\n });\n }, []);\n\n const navigateDown = useCallback(() => {\n setState((prev) => {\n switch (prev.viewMode) {\n case \"feeds\":\n return {\n ...prev,\n selectedFeedIndex: Math.min(\n options.feedsCount - 1,\n prev.selectedFeedIndex + 1\n ),\n };\n case \"posts\":\n return {\n ...prev,\n selectedPostIndex: Math.min(\n options.postsCount - 1,\n prev.selectedPostIndex + 1\n ),\n };\n case \"comments\":\n return {\n ...prev,\n selectedCommentIndex: Math.min(\n options.commentsCount - 1,\n prev.selectedCommentIndex + 1\n ),\n };\n case \"profile\":\n return {\n ...prev,\n selectedProfileIndex: Math.min(\n options.profileItemsCount - 1,\n prev.selectedProfileIndex + 1\n ),\n };\n default:\n return prev;\n }\n });\n }, [options.feedsCount, options.postsCount, options.commentsCount, options.profileItemsCount]);\n\n const selectItem = useCallback(() => {\n switch (state.viewMode) {\n case \"feeds\":\n if (options.onSelectFeed) {\n options.onSelectFeed(state.selectedFeedIndex);\n }\n pushAndNavigate(\"posts\", { key: \"selectedPostIndex\", value: 0 });\n break;\n case \"posts\":\n if (options.onSelectPost) {\n options.onSelectPost(state.selectedPostIndex);\n }\n pushAndNavigate(\"comments\", { key: \"selectedCommentIndex\", value: 0 });\n break;\n case \"profile\":\n if (options.onSelectProfileItem) {\n options.onSelectProfileItem(state.selectedProfileIndex);\n }\n pushAndNavigate(\"posts\", { key: \"selectedPostIndex\", value: 0 });\n break;\n default:\n break;\n }\n }, [state.viewMode, state.selectedFeedIndex, state.selectedPostIndex, state.selectedProfileIndex, options.onSelectFeed, options.onSelectPost, options.onSelectProfileItem, pushAndNavigate]);\n\n const goBack = useCallback(() => {\n // For compose/filter/search, just go back to posts without popping stack\n if (state.viewMode === \"compose\" || state.viewMode === \"filter\") {\n setState((prev) => ({ ...prev, viewMode: \"posts\" }));\n return;\n }\n\n // Pop from stack and restore state\n const previousEntry = navStackRef.current.pop();\n if (previousEntry && options.onRestoreState) {\n options.onRestoreState(previousEntry);\n setState({\n viewMode: previousEntry.viewMode,\n selectedFeedIndex: previousEntry.selectedFeedIndex,\n selectedPostIndex: previousEntry.selectedPostIndex,\n selectedCommentIndex: previousEntry.selectedCommentIndex,\n selectedProfileIndex: previousEntry.selectedProfileIndex,\n });\n } else if (state.viewMode !== \"feeds\") {\n // Fallback: go to feeds if stack is empty\n setState((prev) => ({ ...prev, viewMode: \"feeds\" }));\n }\n }, [state.viewMode, options.onRestoreState]);\n\n const startCompose = useCallback(() => {\n if (options.onCompose) {\n setState((prev) => ({ ...prev, viewMode: \"compose\" }));\n options.onCompose();\n }\n }, [options.onCompose]);\n\n const startFilter = useCallback(() => {\n if (options.onFilter) {\n setState((prev) => ({ ...prev, viewMode: \"filter\" }));\n options.onFilter();\n }\n }, [options.onFilter]);\n\n const startSearch = useCallback(() => {\n if (options.onSearch) {\n // Push current state before search\n navStackRef.current.push(createSnapshot());\n setState((prev) => ({ ...prev, viewMode: \"search\" }));\n options.onSearch();\n }\n }, [options.onSearch, createSnapshot]);\n\n const viewProfile = useCallback(() => {\n if (options.onViewProfile) {\n pushAndNavigate(\"profile\", { key: \"selectedProfileIndex\", value: 0 });\n options.onViewProfile();\n }\n }, [options.onViewProfile, pushAndNavigate]);\n\n const goHome = useCallback(() => {\n // Clear the stack when going home\n navStackRef.current = [];\n if (options.onGoHome) {\n options.onGoHome();\n }\n setState({\n viewMode: \"feeds\",\n selectedFeedIndex: 0,\n selectedPostIndex: 0,\n selectedCommentIndex: 0,\n selectedProfileIndex: 0,\n });\n }, [options.onGoHome]);\n\n useInput((input, key) => {\n // Don't handle input in compose, filter, or search mode\n if (state.viewMode === \"compose\" || state.viewMode === \"filter\" || state.viewMode === \"search\") return;\n\n if (input === \"q\") {\n options.onQuit();\n } else if (input === \"j\" || key.downArrow) {\n navigateDown();\n } else if (input === \"k\" || key.upArrow) {\n navigateUp();\n } else if (key.return) {\n selectItem();\n } else if (key.escape) {\n goBack();\n } else if (input === \"r\") {\n options.onRefresh();\n } else if (input === \"h\") {\n goHome();\n } else if (input === \"/\") {\n startSearch();\n } else if (input === \"p\" && (state.viewMode === \"posts\" || state.viewMode === \"comments\")) {\n viewProfile();\n } else if (input === \"f\" && state.viewMode === \"posts\") {\n startFilter();\n } else if (input === \"u\" && state.viewMode === \"posts\") {\n // Toggle user filter\n if (options.onToggleUserFilter) {\n options.onToggleUserFilter();\n }\n } else if (input === \"?\") {\n // Show help\n if (options.onShowHelp) {\n options.onShowHelp();\n }\n }\n });\n\n const setViewMode = useCallback((mode: ViewMode) => {\n setState((prev) => ({ ...prev, viewMode: mode }));\n }, []);\n\n return {\n ...state,\n setViewMode,\n navigateUp,\n navigateDown,\n selectItem,\n goBack,\n };\n}\n","import { useState, useEffect } from \"react\";\nimport { useStdout } from \"ink\";\n\ninterface ViewportInfo {\n /** Terminal height in rows */\n terminalHeight: number;\n /** Available height for list items (accounting for chrome) */\n availableHeight: number;\n /** First visible item index */\n startIndex: number;\n /** Last visible item index (exclusive) */\n endIndex: number;\n}\n\ninterface UseViewportOptions {\n /** Total number of items */\n itemCount: number;\n /** Currently selected index */\n selectedIndex: number;\n /** Lines reserved for header/footer chrome */\n reservedLines?: number;\n /** Estimated lines per item (for variable height items) */\n linesPerItem?: number;\n}\n\n/**\n * Hook to calculate visible viewport for scrollable lists\n */\nexport function useViewport({\n itemCount,\n selectedIndex,\n reservedLines = 6, // header, status bar, padding, etc.\n linesPerItem = 3, // most items are 2-3 lines (content + metadata + margin)\n}: UseViewportOptions): ViewportInfo {\n const { stdout } = useStdout();\n const [terminalHeight, setTerminalHeight] = useState(stdout?.rows ?? 24);\n\n useEffect(() => {\n if (!stdout) return;\n\n const handleResize = () => {\n setTerminalHeight(stdout.rows);\n };\n\n // Initial size\n setTerminalHeight(stdout.rows);\n\n // Listen for resize\n stdout.on(\"resize\", handleResize);\n return () => {\n stdout.off(\"resize\", handleResize);\n };\n }, [stdout]);\n\n const availableHeight = Math.max(terminalHeight - reservedLines, 5);\n const visibleItemCount = Math.max(Math.floor(availableHeight / linesPerItem), 1);\n\n // Calculate window that keeps selected item visible\n // Try to keep selected item roughly centered, but clamp to valid range\n let startIndex = Math.max(0, selectedIndex - Math.floor(visibleItemCount / 2));\n\n // Ensure we don't go past the end\n if (startIndex + visibleItemCount > itemCount) {\n startIndex = Math.max(0, itemCount - visibleItemCount);\n }\n\n const endIndex = Math.min(startIndex + visibleItemCount, itemCount);\n\n return {\n terminalHeight,\n availableHeight,\n startIndex,\n endIndex,\n };\n}\n","import React from \"react\";\nimport { Box, Text } from \"ink\";\nimport type { RegisteredFeed } from \"@net-protocol/feeds\";\nimport { useViewport } from \"../hooks\";\n\ninterface FeedListProps {\n feeds: RegisteredFeed[];\n selectedIndex: number;\n loading: boolean;\n error: Error | null;\n}\n\nexport function FeedList({\n feeds,\n selectedIndex,\n loading,\n error,\n}: FeedListProps) {\n const { startIndex, endIndex } = useViewport({\n itemCount: feeds.length,\n selectedIndex,\n reservedLines: 7, // header + hint + status bar + padding\n linesPerItem: 1,\n });\n\n if (loading) {\n return (\n <Box flexDirection=\"column\" padding={1}>\n <Text color=\"yellow\">Loading feeds...</Text>\n </Box>\n );\n }\n\n if (error) {\n return (\n <Box flexDirection=\"column\" padding={1}>\n <Text color=\"red\">Error: {error.message}</Text>\n </Box>\n );\n }\n\n const visibleFeeds = feeds.slice(startIndex, endIndex);\n const hasMoreAbove = startIndex > 0;\n const hasMoreBelow = endIndex < feeds.length;\n\n return (\n <Box flexDirection=\"column\" padding={1}>\n <Text bold color=\"cyan\">\n Registered Feeds {feeds.length > 0 && `(${feeds.length})`}\n </Text>\n <Box marginTop={1}>\n <Text color=\"gray\" dimColor>\n Press \"/\" to search any feed or profile\n </Text>\n </Box>\n {hasMoreAbove && (\n <Text color=\"gray\" dimColor> ↑ {startIndex} more above</Text>\n )}\n <Box flexDirection=\"column\" marginTop={hasMoreAbove ? 0 : 1}>\n {feeds.length === 0 ? (\n <Text color=\"gray\">No registered feeds found</Text>\n ) : (\n visibleFeeds.map((feed, index) => {\n const actualIndex = startIndex + index;\n const isSelected = actualIndex === selectedIndex;\n return (\n <Text\n key={`${feed.feedName}-${actualIndex}`}\n color={isSelected ? \"green\" : undefined}\n bold={isSelected}\n >\n {isSelected ? \"▶ \" : \" \"}\n {feed.feedName}\n </Text>\n );\n })\n )}\n </Box>\n {hasMoreBelow && (\n <Text color=\"gray\" dimColor> ↓ {feeds.length - endIndex} more below</Text>\n )}\n </Box>\n );\n}\n","import React from \"react\";\nimport { Box, Text } from \"ink\";\nimport type { NetMessage } from \"@net-protocol/feeds\";\nimport { useViewport } from \"../hooks\";\n\ninterface PostListProps {\n feedName: string;\n posts: NetMessage[];\n commentCounts: Map<string, number>;\n selectedIndex: number;\n loading: boolean;\n error: Error | null;\n}\n\nfunction truncateAddress(address: string): string {\n if (address.length <= 12) return address;\n return `${address.slice(0, 6)}...${address.slice(-4)}`;\n}\n\nfunction isAddress(str: string): boolean {\n return /^0x[a-fA-F0-9]{40}$/.test(str);\n}\n\nfunction formatFeedName(feedName: string): string {\n // Strip \"feed-\" prefix if present\n let name = feedName;\n if (name.startsWith(\"feed-\")) {\n name = name.slice(5);\n }\n // If it's an address, truncate it\n if (isAddress(name)) {\n return `@${truncateAddress(name)}`;\n }\n return name;\n}\n\nfunction formatTimestamp(timestamp: bigint): string {\n const date = new Date(Number(timestamp) * 1000);\n return date.toLocaleString(\"en-US\", {\n month: \"short\",\n day: \"numeric\",\n hour: \"2-digit\",\n minute: \"2-digit\",\n });\n}\n\n/** Parse post text into title (first line) and body (rest) */\nfunction parsePostContent(text: string | undefined): { title: string; body: string | null } {\n if (!text) return { title: \"\", body: null };\n\n const firstNewline = text.indexOf(\"\\n\");\n if (firstNewline === -1) {\n // No newline - entire text is title\n return { title: text.trim(), body: null };\n }\n\n const title = text.slice(0, firstNewline).trim();\n const body = text.slice(firstNewline + 1).trim();\n\n return { title, body: body || null };\n}\n\n/** Truncate text for post display, preserving wrapping */\nfunction truncateText(text: string, maxLength = 250): string {\n const trimmed = text.trim();\n if (trimmed.length <= maxLength) return trimmed;\n return trimmed.slice(0, maxLength - 3) + \"...\";\n}\n\nexport function PostList({\n feedName,\n posts,\n commentCounts,\n selectedIndex,\n loading,\n error,\n}: PostListProps) {\n const { startIndex, endIndex } = useViewport({\n itemCount: posts.length,\n selectedIndex,\n reservedLines: 6, // header + status bar + padding\n linesPerItem: 3, // title + metadata + margin\n });\n\n if (loading) {\n return (\n <Box flexDirection=\"column\" padding={1}>\n <Text color=\"yellow\">Loading posts...</Text>\n </Box>\n );\n }\n\n if (error) {\n return (\n <Box flexDirection=\"column\" padding={1}>\n <Text color=\"red\">Error: {error.message}</Text>\n </Box>\n );\n }\n\n if (posts.length === 0) {\n return (\n <Box flexDirection=\"column\" padding={1}>\n <Text color=\"gray\">No posts in {formatFeedName(feedName)}</Text>\n </Box>\n );\n }\n\n const visiblePosts = posts.slice(startIndex, endIndex);\n const hasMoreAbove = startIndex > 0;\n const hasMoreBelow = endIndex < posts.length;\n\n return (\n <Box flexDirection=\"column\" padding={1}>\n <Text bold color=\"cyan\">\n {formatFeedName(feedName)} ({posts.length} posts)\n </Text>\n {hasMoreAbove && (\n <Text color=\"gray\" dimColor> ↑ {startIndex} more above</Text>\n )}\n <Box flexDirection=\"column\" marginTop={hasMoreAbove ? 0 : 1}>\n {visiblePosts.map((post, index) => {\n const actualIndex = startIndex + index;\n const isSelected = actualIndex === selectedIndex;\n const postKey = `${post.sender}:${post.timestamp}`;\n const commentCount = commentCounts.get(postKey) ?? 0;\n const { title, body } = parsePostContent(post.text);\n const displayTitle = title ? truncateText(title) : null;\n const hasMore = body !== null;\n\n return (\n <Box\n key={postKey}\n flexDirection=\"column\"\n marginBottom={1}\n >\n <Text\n color={isSelected ? \"green\" : undefined}\n bold={isSelected}\n >\n {isSelected ? \"▶ \" : \" \"}\n {displayTitle || <Text color=\"gray\" dimColor>(no text)</Text>}\n {hasMore && <Text color=\"gray\" dimColor> [...]</Text>}\n </Text>\n <Text color=\"gray\" dimColor>\n {\" \"}\n {truncateAddress(post.sender)} · {formatTimestamp(post.timestamp)} · {commentCount} comment{commentCount !== 1 ? \"s\" : \"\"}\n </Text>\n </Box>\n );\n })}\n </Box>\n {hasMoreBelow && (\n <Text color=\"gray\" dimColor> ↓ {posts.length - endIndex} more below</Text>\n )}\n </Box>\n );\n}\n","import React from \"react\";\nimport { Box, Text, useStdout } from \"ink\";\nimport type { NetMessage } from \"@net-protocol/feeds\";\nimport type { CommentWithDepth } from \"../hooks\";\n\ninterface CommentTreeProps {\n post: NetMessage;\n comments: CommentWithDepth[];\n replyCounts: Map<string, number>;\n selectedIndex: number; // 0 = post, 1+ = comments\n loading: boolean;\n error: Error | null;\n}\n\nfunction truncateAddress(address: string): string {\n if (address.length <= 12) return address;\n return `${address.slice(0, 6)}...${address.slice(-4)}`;\n}\n\nfunction formatTimestamp(timestamp: bigint): string {\n const date = new Date(Number(timestamp) * 1000);\n return date.toLocaleString(\"en-US\", {\n month: \"short\",\n day: \"numeric\",\n hour: \"2-digit\",\n minute: \"2-digit\",\n });\n}\n\n/** Truncate text for comment display, preserving some line breaks */\nfunction truncateText(text: string, maxLength = 500): string {\n const trimmed = text.trim();\n if (trimmed.length <= maxLength) return trimmed;\n return trimmed.slice(0, maxLength - 3) + \"...\";\n}\n\n/** Split text into lines, accounting for terminal width wrapping */\nfunction getTextLines(text: string, width: number): string[] {\n const lines: string[] = [];\n const rawLines = text.split(\"\\n\");\n\n for (const rawLine of rawLines) {\n if (rawLine.length === 0) {\n lines.push(\"\");\n } else if (rawLine.length <= width) {\n lines.push(rawLine);\n } else {\n // Wrap long lines\n let remaining = rawLine;\n while (remaining.length > 0) {\n lines.push(remaining.slice(0, width));\n remaining = remaining.slice(width);\n }\n }\n }\n\n return lines;\n}\n\nexport function CommentTree({\n post,\n comments,\n replyCounts,\n selectedIndex,\n loading,\n error,\n}: CommentTreeProps) {\n const { stdout } = useStdout();\n const terminalHeight = stdout?.rows ?? 24;\n const terminalWidth = stdout?.columns ?? 80;\n\n // Reserve lines for header, status bar, padding\n const reservedLines = 6;\n const availableHeight = terminalHeight - reservedLines;\n\n // selectedIndex: 0 = post, 1+ = comments (comment index = selectedIndex - 1)\n const isPostSelected = selectedIndex === 0;\n const selectedCommentIndex = selectedIndex - 1;\n\n if (loading) {\n return (\n <Box flexDirection=\"column\" padding={1}>\n <Text color=\"yellow\">Loading post...</Text>\n </Box>\n );\n }\n\n if (error) {\n return (\n <Box flexDirection=\"column\" padding={1}>\n <Text color=\"red\">Error: {error.message}</Text>\n </Box>\n );\n }\n\n // Calculate post content - leave room for selector prefix \"▶ \" (2 chars) and left margin\n const contentWidth = Math.max(40, terminalWidth - 8);\n const postText = post.text ?? \"\";\n const postLines = getTextLines(postText, contentWidth);\n\n const linesPerComment = 3;\n\n // Determine how many post lines to show based on selection\n // When post is selected, show more of the post; when comment selected, show less\n const maxPostLines = isPostSelected\n ? Math.max(3, availableHeight - 6) // Leave room for header, metadata, comments header, some comments\n : 3; // Show preview when viewing comments\n\n const displayPostLines = postLines.slice(0, maxPostLines);\n const postHasMore = postLines.length > maxPostLines;\n\n // Calculate comment viewport\n // Reserve: Post header (1) + post lines + post metadata (1) + post \"more\" indicator (1 if needed)\n // + Comments header (1) + scroll indicators (2)\n const postOverhead = 1 + displayPostLines.length + 1 + (postHasMore ? 1 : 0) + 1 + 2;\n const linesForComments = Math.max(3, availableHeight - postOverhead);\n const visibleCommentCount = Math.floor(linesForComments / linesPerComment);\n\n // Calculate comment window to keep selected comment visible\n let commentStartIndex = 0;\n if (selectedCommentIndex > 0) {\n // Keep selected comment in view (only scroll when a comment is actually selected)\n commentStartIndex = Math.max(0, selectedCommentIndex - Math.floor(visibleCommentCount / 2));\n if (commentStartIndex + visibleCommentCount > comments.length) {\n commentStartIndex = Math.max(0, comments.length - visibleCommentCount);\n }\n }\n // When post is selected (selectedCommentIndex = -1), start from beginning\n const commentEndIndex = Math.min(commentStartIndex + visibleCommentCount, comments.length);\n const visibleComments = comments.slice(commentStartIndex, commentEndIndex);\n\n const hasMoreCommentsAbove = commentStartIndex > 0;\n const hasMoreCommentsBelow = commentEndIndex < comments.length;\n\n return (\n <Box flexDirection=\"column\" padding={1}>\n {/* Post section */}\n <Text bold color=\"cyan\">Post</Text>\n <Box marginLeft={1}>\n <Text color={isPostSelected ? \"green\" : undefined} bold={isPostSelected}>\n {isPostSelected ? \"▶ \" : \" \"}\n </Text>\n <Box flexDirection=\"column\" width={contentWidth}>\n {displayPostLines.length === 0 ? (\n <Text color=\"gray\">(no text)</Text>\n ) : (\n displayPostLines.map((line, i) => (\n <Text key={i} color={isPostSelected ? \"green\" : undefined} wrap=\"truncate-end\">\n {line || \" \"}\n </Text>\n ))\n )}\n {postHasMore && (\n <Text color=\"gray\" dimColor>\n {isPostSelected ? \"↓ \" : \"↑ \"}{postLines.length - maxPostLines} more lines\n </Text>\n )}\n </Box>\n </Box>\n <Text color=\"gray\">\n {\" \"}{truncateAddress(post.sender)} · {formatTimestamp(post.timestamp)}\n </Text>\n\n {/* Comments section */}\n <Box marginTop={1}>\n <Text bold color=\"cyan\">Comments ({comments.length})</Text>\n </Box>\n\n {comments.length === 0 ? (\n <Box marginTop={1} marginLeft={1}>\n <Text color=\"gray\">No comments yet</Text>\n </Box>\n ) : (\n <Box flexDirection=\"column\">\n {hasMoreCommentsAbove && (\n <Text color=\"gray\" dimColor>\n {\" ↑ \"}{commentStartIndex} more above\n </Text>\n )}\n {visibleComments.map((item, index) => {\n const actualIndex = commentStartIndex + index;\n const isSelected = actualIndex === selectedCommentIndex;\n const { comment, depth } = item;\n const key = `${comment.sender}:${comment.timestamp}`;\n const replyCount = replyCounts.get(key) ?? 0;\n const displayText = comment.text ? truncateText(comment.text) : null;\n\n // Indentation based on nesting depth\n const indent = \" \".repeat(depth);\n const replyIndicator = depth > 0 ? \"↳ \" : \"\";\n\n return (\n <Box\n key={key}\n flexDirection=\"column\"\n marginLeft={1}\n marginBottom={1}\n >\n <Text\n color={isSelected ? \"green\" : undefined}\n bold={isSelected}\n >\n {indent}{isSelected ? \"▶ \" : \" \"}{replyIndicator}\n {displayText || <Text color=\"gray\" dimColor>(no text)</Text>}\n </Text>\n <Text color=\"gray\">\n {indent}{\" \"}\n {truncateAddress(comment.sender)} · {formatTimestamp(comment.timestamp)}\n {replyCount > 0 && ` · ${replyCount} ${replyCount === 1 ? \"reply\" : \"replies\"}`}\n </Text>\n </Box>\n );\n })}\n {hasMoreCommentsBelow && (\n <Text color=\"gray\" dimColor>\n {\" ↓ \"}{comments.length - commentEndIndex} more below\n </Text>\n )}\n </Box>\n )}\n </Box>\n );\n}\n","import React from \"react\";\nimport { Box, Text } from \"ink\";\nimport { useViewport } from \"../hooks\";\nimport type { ProfileMessage } from \"../hooks\";\n\ninterface ProfileProps {\n address: string;\n activityMessages: ProfileMessage[];\n loading: boolean;\n error: Error | null;\n selectedIndex: number; // 0 = \"Their Feed\" option, 1+ = Active On feeds\n}\n\nfunction truncateAddress(address: string): string {\n if (address.length <= 12) return address;\n return `${address.slice(0, 6)}...${address.slice(-4)}`;\n}\n\n/** Parse topic to get clean feed name (strips \"feed-\" prefix and comment suffix) */\nfunction cleanFeedName(topic: string): string {\n // Remove :comments:... suffix\n let clean = topic.split(\":comments:\")[0];\n // Strip \"feed-\" prefix if present\n if (clean.startsWith(\"feed-\")) {\n clean = clean.slice(5);\n }\n return clean;\n}\n\n/** Aggregate messages by feed for Active On view */\nexport interface FeedActivity {\n topic: string; // Topic for navigation (with feed- prefix)\n feedName: string; // Display name (without feed- prefix)\n postCount: number;\n lastActive: bigint;\n}\n\nexport function aggregateByFeed(messages: ProfileMessage[]): FeedActivity[] {\n const feedMap = new Map<string, FeedActivity>();\n\n for (const { message, topic } of messages) {\n // Skip comments - only show posts in Active On\n if (topic.includes(\":comments:\")) {\n continue;\n }\n\n const feedName = cleanFeedName(topic);\n // Use feedName as key to avoid duplicates from \"feed-X\" vs \"X\"\n const existing = feedMap.get(feedName);\n if (existing) {\n existing.postCount++;\n if (message.timestamp > existing.lastActive) {\n existing.lastActive = message.timestamp;\n }\n } else {\n feedMap.set(feedName, {\n topic, // Keep original topic for navigation\n feedName,\n postCount: 1,\n lastActive: message.timestamp,\n });\n }\n }\n\n // Sort by most recently active\n return Array.from(feedMap.values()).sort(\n (a, b) => Number(b.lastActive - a.lastActive)\n );\n}\n\nexport function Profile({\n address,\n activityMessages,\n loading,\n error,\n selectedIndex,\n}: ProfileProps) {\n // Aggregate activity messages by feed\n const aggregatedFeeds = React.useMemo(\n () => aggregateByFeed(activityMessages),\n [activityMessages]\n );\n\n // Total items: 1 (\"Their Feed\" option) + aggregated feeds\n const totalItems = 1 + aggregatedFeeds.length;\n\n const { startIndex, endIndex } = useViewport({\n itemCount: totalItems,\n selectedIndex,\n reservedLines: 6,\n linesPerItem: 2,\n });\n\n if (loading) {\n return (\n <Box flexDirection=\"column\" padding={1}>\n <Text color=\"yellow\">Loading profile...</Text>\n </Box>\n );\n }\n\n if (error) {\n return (\n <Box flexDirection=\"column\" padding={1}>\n <Text color=\"red\">Error: {error.message}</Text>\n </Box>\n );\n }\n\n const hasMoreAbove = startIndex > 0;\n const hasMoreBelow = endIndex < totalItems;\n\n // Build visible items list\n const visibleItems: React.ReactNode[] = [];\n\n for (let i = startIndex; i < endIndex; i++) {\n const isSelected = i === selectedIndex;\n\n if (i === 0) {\n // \"Their Feed\" option - view posts TO this address\n visibleItems.push(\n <Box key=\"their-feed\" flexDirection=\"column\" marginBottom={1}>\n <Text\n color={isSelected ? \"green\" : undefined}\n bold={isSelected}\n >\n {isSelected ? \"▶ \" : \" \"}\n <Text color={isSelected ? \"green\" : \"magenta\"}>@{truncateAddress(address)}</Text>\n <Text color=\"gray\"> · view their feed</Text>\n </Text>\n </Box>\n );\n } else {\n // Active On feeds (index - 1 because first item is \"Their Feed\")\n const feed = aggregatedFeeds[i - 1];\n if (feed) {\n const postLabel = `${feed.postCount} post${feed.postCount !== 1 ? \"s\" : \"\"}`;\n visibleItems.push(\n <Box key={feed.topic} flexDirection=\"column\" marginBottom={1}>\n <Text\n color={isSelected ? \"green\" : undefined}\n bold={isSelected}\n >\n {isSelected ? \"▶ \" : \" \"}\n <Text color={isSelected ? \"green\" : \"cyan\"}>{feed.feedName}</Text>\n <Text color=\"gray\"> · {postLabel}</Text>\n </Text>\n </Box>\n );\n }\n }\n }\n\n return (\n <Box flexDirection=\"column\" padding={1}>\n {/* Header with address */}\n <Text bold color=\"cyan\">\n {truncateAddress(address)}\n </Text>\n\n {/* Section labels */}\n <Box marginTop={1} marginBottom={1}>\n <Text color=\"gray\">Their Feed</Text>\n <Text color=\"gray\"> · </Text>\n <Text color=\"gray\">Active On ({aggregatedFeeds.length})</Text>\n </Box>\n\n {hasMoreAbove && (\n <Text color=\"gray\" dimColor> ↑ {startIndex} more above</Text>\n )}\n\n <Box flexDirection=\"column\" marginTop={hasMoreAbove ? 0 : 0}>\n {visibleItems}\n </Box>\n\n {hasMoreBelow && (\n <Text color=\"gray\" dimColor> ↓ {totalItems - endIndex} more below</Text>\n )}\n </Box>\n );\n}\n","import React from \"react\";\nimport { Box, Text } from \"ink\";\nimport type { ViewMode } from \"../hooks\";\n\ninterface HeaderProps {\n viewMode: ViewMode;\n chainId: number;\n feedName?: string | null;\n senderFilter?: string;\n profileAddress?: string | null;\n}\n\nfunction truncateAddress(address: string): string {\n if (address.length <= 12) return address;\n return `${address.slice(0, 6)}...${address.slice(-4)}`;\n}\n\nfunction isAddress(str: string): boolean {\n return /^0x[a-fA-F0-9]{40}$/.test(str);\n}\n\nfunction formatFeedName(feedName: string): string {\n // Strip \"feed-\" prefix if present\n let name = feedName;\n if (name.startsWith(\"feed-\")) {\n name = name.slice(5);\n }\n // If it's an address, truncate it\n if (isAddress(name)) {\n return `@${truncateAddress(name)}`;\n }\n return name;\n}\n\nfunction getChainName(chainId: number): string {\n switch (chainId) {\n case 1:\n return \"mainnet\";\n case 8453:\n return \"base\";\n case 84532:\n return \"base-sepolia\";\n default:\n return `chain:${chainId}`;\n }\n}\n\nexport function Header({ viewMode, chainId, feedName, senderFilter, profileAddress }: HeaderProps) {\n // Build breadcrumb based on current view\n const getBreadcrumb = () => {\n const parts: React.ReactNode[] = [];\n\n if (viewMode === \"profile\" && profileAddress) {\n parts.push(<Text key=\"profile\" color=\"white\">profile</Text>);\n parts.push(<Text key=\"sep\" color=\"gray\"> · </Text>);\n parts.push(<Text key=\"address\" color=\"magenta\">{truncateAddress(profileAddress)}</Text>);\n } else if (viewMode === \"feeds\" || viewMode === \"search\") {\n parts.push(<Text key=\"home\" color=\"white\">home</Text>);\n } else if (feedName) {\n parts.push(<Text key=\"feed\" color=\"white\">{formatFeedName(feedName)}</Text>);\n if (viewMode === \"comments\") {\n parts.push(<Text key=\"sep\" color=\"gray\"> > </Text>);\n parts.push(<Text key=\"post\" color=\"white\">post</Text>);\n }\n }\n\n if (senderFilter && viewMode !== \"profile\") {\n parts.push(<Text key=\"filter-sep\" color=\"gray\"> </Text>);\n parts.push(<Text key=\"filter\" color=\"magenta\">[{truncateAddress(senderFilter)}]</Text>);\n }\n\n return parts;\n };\n\n return (\n <Box\n borderStyle=\"single\"\n borderColor=\"cyan\"\n paddingX={1}\n justifyContent=\"space-between\"\n >\n <Box>\n <Text color=\"cyan\" bold>\n botchan\n </Text>\n <Text color=\"gray\"> · </Text>\n <Text color=\"gray\" dimColor>\n onchain messaging for agents\n </Text>\n </Box>\n <Box>\n {getBreadcrumb()}\n <Text color=\"gray\"> · </Text>\n <Text color=\"green\">{getChainName(chainId)}</Text>\n </Box>\n </Box>\n );\n}\n","import React from \"react\";\nimport { Box, Text } from \"ink\";\nimport type { ViewMode } from \"../hooks\";\n\ninterface StatusBarProps {\n viewMode: ViewMode;\n}\n\nexport function StatusBar({ viewMode }: StatusBarProps) {\n const getContextHints = () => {\n switch (viewMode) {\n case \"feeds\":\n return \"j/k navigate · enter select · / search · r refresh · ? help · q quit\";\n case \"posts\":\n return \"j/k navigate · enter view · p profile · u toggle user · f filter · ? help · q quit\";\n case \"comments\":\n return \"j/k navigate · p profile · esc back · ? help · q quit\";\n case \"profile\":\n return \"j/k navigate · enter select · esc back · ? help · q quit\";\n case \"compose\":\n return \"type message · enter submit · esc cancel\";\n case \"filter\":\n return \"enter address · enter apply · esc cancel\";\n case \"search\":\n return \"enter feed name · enter go · esc cancel\";\n default:\n return \"\";\n }\n };\n\n return (\n <Box paddingX={1}>\n <Text color=\"gray\">\n {getContextHints()}\n </Text>\n </Box>\n );\n}\n","import React, { useState } from \"react\";\nimport { Box, Text, useInput } from \"ink\";\n\ninterface PostInputProps {\n feedName: string;\n onSubmit: (text: string) => void;\n onCancel: () => void;\n}\n\nexport function PostInput({ feedName, onSubmit, onCancel }: PostInputProps) {\n const [text, setText] = useState(\"\");\n\n useInput((input, key) => {\n if (key.escape) {\n onCancel();\n } else if (key.return) {\n if (text.trim()) {\n onSubmit(text.trim());\n }\n } else if (key.backspace || key.delete) {\n setText((prev) => prev.slice(0, -1));\n } else if (input && !key.ctrl && !key.meta) {\n setText((prev) => prev + input);\n }\n });\n\n return (\n <Box flexDirection=\"column\" padding={1}>\n <Text bold color=\"cyan\">\n New Post to {feedName}\n </Text>\n <Box marginTop={1} flexDirection=\"column\">\n <Text color=\"gray\">Enter your message (Esc to cancel):</Text>\n <Box marginTop={1} borderStyle=\"single\" borderColor=\"gray\" padding={1}>\n <Text>\n {text}\n <Text color=\"cyan\">█</Text>\n </Text>\n </Box>\n </Box>\n <Box marginTop={1}>\n <Text color=\"gray\" dimColor>\n Press Enter to submit\n </Text>\n </Box>\n </Box>\n );\n}\n","import React, { useState } from \"react\";\nimport { Box, Text, useInput } from \"ink\";\n\ninterface SenderFilterProps {\n onSubmit: (address: string) => void;\n onCancel: () => void;\n}\n\nexport function SenderFilter({ onSubmit, onCancel }: SenderFilterProps) {\n const [text, setText] = useState(\"\");\n\n useInput((input, key) => {\n if (key.escape) {\n onCancel();\n } else if (key.return) {\n // Allow empty to clear filter, normalize address to lowercase\n const trimmed = text.trim();\n onSubmit(trimmed ? trimmed.toLowerCase() : \"\");\n } else if (key.backspace || key.delete) {\n setText((prev) => prev.slice(0, -1));\n } else if (input && !key.ctrl && !key.meta) {\n setText((prev) => prev + input);\n }\n });\n\n return (\n <Box flexDirection=\"column\" padding={1}>\n <Text bold color=\"cyan\">\n Filter by Sender Address\n </Text>\n <Box marginTop={1} flexDirection=\"column\">\n <Text color=\"gray\">Enter address (or empty to clear filter):</Text>\n <Box marginTop={1} borderStyle=\"single\" borderColor=\"gray\" padding={1}>\n <Text>\n {text || <Text color=\"gray\">0x...</Text>}\n <Text color=\"cyan\">█</Text>\n </Text>\n </Box>\n </Box>\n <Box marginTop={1}>\n <Text color=\"gray\" dimColor>\n Enter: apply filter | Esc: cancel\n </Text>\n </Box>\n </Box>\n );\n}\n","import chalk from \"chalk\";\n\n/**\n * Default chain ID (Base mainnet)\n */\nexport const DEFAULT_CHAIN_ID = 8453;\n\n/**\n * Normalize a feed name to lowercase for consistency.\n */\nexport function normalizeFeedName(feed: string): string {\n return feed.toLowerCase();\n}\n\n/**\n * Common options shared across all CLI commands\n */\nexport interface CommonOptions {\n privateKey: `0x${string}`;\n chainId: number;\n rpcUrl?: string;\n}\n\n/**\n * Read-only options for commands that don't need a private key\n */\nexport interface ReadOnlyOptions {\n chainId: number;\n rpcUrl?: string;\n}\n\n/**\n * Get chain ID from option or environment variable\n */\nfunction getChainId(optionValue?: number): number {\n if (optionValue) {\n return optionValue;\n }\n\n const envChainId =\n process.env.BOTCHAN_CHAIN_ID || process.env.NET_CHAIN_ID;\n\n if (envChainId) {\n return parseInt(envChainId, 10);\n }\n\n return DEFAULT_CHAIN_ID;\n}\n\n/**\n * Get RPC URL from option or environment variable\n */\nfunction getRpcUrl(optionValue?: string): string | undefined {\n return optionValue || process.env.BOTCHAN_RPC_URL || process.env.NET_RPC_URL;\n}\n\n/**\n * Parse and validate read-only options for commands that don't need a private key.\n * Extracts chain ID and RPC URL from command options or environment variables.\n */\nexport function parseReadOnlyOptions(options: {\n chainId?: number;\n rpcUrl?: string;\n}): ReadOnlyOptions {\n return {\n chainId: getChainId(options.chainId),\n rpcUrl: getRpcUrl(options.rpcUrl),\n };\n}\n\n/**\n * Parse and validate common options shared across all commands.\n * Extracts private key, chain ID, and RPC URL from command options or environment variables.\n * @param options - Command options\n * @param supportsEncodeOnly - If true, mention --encode-only in error messages as an alternative\n */\nexport function parseCommonOptions(\n options: {\n privateKey?: string;\n chainId?: number;\n rpcUrl?: string;\n },\n supportsEncodeOnly = false\n): CommonOptions {\n const privateKey =\n options.privateKey ||\n process.env.BOTCHAN_PRIVATE_KEY ||\n process.env.NET_PRIVATE_KEY ||\n process.env.PRIVATE_KEY;\n\n if (!privateKey) {\n const encodeOnlyHint = supportsEncodeOnly\n ? \", or use --encode-only to output transaction data without submitting\"\n : \"\";\n console.error(\n chalk.red(\n `Error: Private key is required. Provide via --private-key flag or BOTCHAN_PRIVATE_KEY/NET_PRIVATE_KEY environment variable${encodeOnlyHint}`\n )\n );\n process.exit(1);\n }\n\n if (!privateKey.startsWith(\"0x\") || privateKey.length !== 66) {\n console.error(\n chalk.red(\n \"Error: Invalid private key format (must be 0x-prefixed, 66 characters)\"\n )\n );\n process.exit(1);\n }\n\n if (options.privateKey) {\n console.warn(\n chalk.yellow(\n \"Warning: Private key provided via command line. Consider using BOTCHAN_PRIVATE_KEY environment variable instead.\"\n )\n );\n }\n\n return {\n privateKey: privateKey as `0x${string}`,\n chainId: getChainId(options.chainId),\n rpcUrl: getRpcUrl(options.rpcUrl),\n };\n}\n","import * as fs from \"fs\";\nimport * as path from \"path\";\nimport * as os from \"os\";\n\ninterface FeedState {\n lastSeenTimestamp: number;\n}\n\ninterface AppState {\n feeds: Record<string, FeedState>;\n myAddress?: string;\n}\n\nconst STATE_DIR = path.join(os.homedir(), \".botchan\");\nconst STATE_FILE = path.join(STATE_DIR, \"state.json\");\n\nfunction ensureStateDir(): void {\n if (!fs.existsSync(STATE_DIR)) {\n fs.mkdirSync(STATE_DIR, { recursive: true });\n }\n}\n\nfunction loadState(): AppState {\n try {\n if (fs.existsSync(STATE_FILE)) {\n const data = fs.readFileSync(STATE_FILE, \"utf-8\");\n return JSON.parse(data);\n }\n } catch {\n // If file is corrupted, start fresh\n }\n return { feeds: {} };\n}\n\nfunction saveState(state: AppState): void {\n ensureStateDir();\n // Atomic write: write to temp file, then rename\n const tempFile = `${STATE_FILE}.tmp`;\n fs.writeFileSync(tempFile, JSON.stringify(state, null, 2));\n fs.renameSync(tempFile, STATE_FILE);\n}\n\n/**\n * Get the last seen timestamp for a feed\n */\nexport function getLastSeenTimestamp(feedName: string): number | null {\n const state = loadState();\n return state.feeds[feedName]?.lastSeenTimestamp ?? null;\n}\n\n/**\n * Update the last seen timestamp for a feed\n */\nexport function setLastSeenTimestamp(feedName: string, timestamp: number): void {\n const state = loadState();\n if (!state.feeds[feedName]) {\n state.feeds[feedName] = { lastSeenTimestamp: timestamp };\n } else {\n state.feeds[feedName].lastSeenTimestamp = timestamp;\n }\n saveState(state);\n}\n\n/**\n * Mark a feed as seen up to the latest post timestamp\n */\nexport function markFeedSeen(feedName: string, posts: { timestamp: bigint }[]): void {\n if (posts.length === 0) return;\n\n // Find the max timestamp\n const maxTimestamp = posts.reduce(\n (max, post) => (post.timestamp > max ? post.timestamp : max),\n posts[0].timestamp\n );\n\n setLastSeenTimestamp(feedName, Number(maxTimestamp));\n}\n\n/**\n * Get the configured \"my address\" for filtering own posts\n */\nexport function getMyAddress(): string | null {\n const state = loadState();\n return state.myAddress ?? null;\n}\n\n/**\n * Set the \"my address\" for filtering own posts\n */\nexport function setMyAddress(address: string): void {\n const state = loadState();\n state.myAddress = address.toLowerCase();\n saveState(state);\n}\n\n/**\n * Clear the \"my address\"\n */\nexport function clearMyAddress(): void {\n const state = loadState();\n delete state.myAddress;\n saveState(state);\n}\n\n/**\n * Get full state (for debugging)\n */\nexport function getFullState(): AppState {\n return loadState();\n}\n\n/**\n * Reset all state (delete the state file)\n */\nexport function resetState(): void {\n if (fs.existsSync(STATE_FILE)) {\n fs.unlinkSync(STATE_FILE);\n }\n}\n\n/**\n * Get the state file path (for display purposes)\n */\nexport function getStateFilePath(): string {\n return STATE_FILE;\n}\n","import React, { useState } from \"react\";\nimport { Box, Text, useInput } from \"ink\";\nimport { normalizeFeedName } from \"../../utils\";\n\ninterface FeedSearchProps {\n onSubmit: (feedName: string) => void;\n onCancel: () => void;\n}\n\nexport function FeedSearch({ onSubmit, onCancel }: FeedSearchProps) {\n const [text, setText] = useState(\"\");\n\n useInput((input, key) => {\n if (key.escape) {\n onCancel();\n } else if (key.return) {\n if (text.trim()) {\n onSubmit(normalizeFeedName(text.trim()));\n }\n } else if (key.backspace || key.delete) {\n setText((prev) => prev.slice(0, -1));\n } else if (input && !key.ctrl && !key.meta) {\n setText((prev) => prev + input);\n }\n });\n\n return (\n <Box flexDirection=\"column\" padding={1}>\n <Text bold color=\"cyan\">\n Go to Feed or Profile\n </Text>\n <Box marginTop={1} flexDirection=\"column\">\n <Text color=\"gray\">\n Enter feed name or wallet address:\n </Text>\n <Text color=\"gray\" dimColor>\n (Feeds don't need to be registered to view them)\n </Text>\n <Box marginTop={1} borderStyle=\"single\" borderColor=\"gray\" padding={1}>\n <Text>\n {text || <Text color=\"gray\">general, 0x1234..., etc</Text>}\n <Text color=\"cyan\">█</Text>\n </Text>\n </Box>\n </Box>\n <Box marginTop={1}>\n <Text color=\"gray\" dimColor>\n Enter: go to feed | Esc: cancel\n </Text>\n </Box>\n </Box>\n );\n}\n","import React from \"react\";\nimport { Box, Text, useInput } from \"ink\";\n\ninterface HelpProps {\n onClose: () => void;\n}\n\nexport function Help({ onClose }: HelpProps) {\n // Close on any key press\n useInput(() => {\n onClose();\n });\n\n return (\n <Box flexDirection=\"column\" padding={1}>\n <Box marginBottom={1}>\n <Text bold color=\"cyan\">botchan</Text>\n <Text color=\"gray\"> · onchain messaging for agents</Text>\n </Box>\n\n <Box flexDirection=\"column\" marginBottom={1}>\n <Text bold color=\"white\">Navigation</Text>\n <Text> <Text color=\"cyan\">j/k ↑/↓</Text> Move up/down</Text>\n <Text> <Text color=\"cyan\">enter</Text> Select / view</Text>\n <Text> <Text color=\"cyan\">esc</Text> Go back</Text>\n <Text> <Text color=\"cyan\">h</Text> Go home</Text>\n <Text> <Text color=\"cyan\">q</Text> Quit</Text>\n </Box>\n\n <Box flexDirection=\"column\" marginBottom={1}>\n <Text bold color=\"white\">Actions</Text>\n <Text> <Text color=\"cyan\">p</Text> View author profile</Text>\n <Text> <Text color=\"cyan\">u</Text> Toggle user filter</Text>\n <Text> <Text color=\"cyan\">f</Text> Filter by address</Text>\n <Text> <Text color=\"cyan\">/</Text> Search feeds</Text>\n <Text> <Text color=\"cyan\">r</Text> Refresh</Text>\n <Text> <Text color=\"cyan\">?</Text> Show this help</Text>\n </Box>\n\n <Box marginTop={1}>\n <Text color=\"gray\" dimColor>Press any key to close</Text>\n </Box>\n </Box>\n );\n}\n","import React, { useState, useCallback } from \"react\";\nimport { Box, useStdout } from \"ink\";\nimport {\n FeedList,\n PostList,\n CommentTree,\n Profile,\n Header,\n StatusBar,\n PostInput,\n SenderFilter,\n FeedSearch,\n Help,\n aggregateByFeed,\n} from \"./components\";\nimport { useFeeds, usePosts, useComments, useProfile, useKeyboard } from \"./hooks\";\nimport type { NavEntry } from \"./hooks\";\nimport type { NetMessage } from \"@net-protocol/feeds\";\n\ninterface AppProps {\n chainId: number;\n rpcUrl?: string;\n onExit: () => void;\n}\n\nexport function App({ chainId, rpcUrl, onExit }: AppProps) {\n const { stdout } = useStdout();\n const terminalHeight = stdout?.rows ?? 24;\n\n const [selectedFeedName, setSelectedFeedName] = useState<string | null>(null);\n const [selectedPost, setSelectedPost] = useState<NetMessage | null>(null);\n const [profileAddress, setProfileAddress] = useState<string | null>(null);\n const [isComposing, setIsComposing] = useState(false);\n const [isFiltering, setIsFiltering] = useState(false);\n const [isSearching, setIsSearching] = useState(false);\n const [isShowingHelp, setIsShowingHelp] = useState(false);\n const [senderFilter, setSenderFilter] = useState<string | undefined>(undefined);\n\n const feedDataOptions = { chainId, rpcUrl, senderFilter };\n\n const {\n feeds,\n loading: feedsLoading,\n error: feedsError,\n refetch: refetchFeeds,\n } = useFeeds({ chainId, rpcUrl });\n\n const {\n posts: rawPosts,\n commentCounts,\n loading: postsLoading,\n error: postsError,\n refetch: refetchPosts,\n } = usePosts(selectedFeedName, feedDataOptions);\n\n // Sort posts by most recent first\n const posts = React.useMemo(\n () => [...rawPosts].sort((a, b) => Number(b.timestamp - a.timestamp)),\n [rawPosts]\n );\n\n const {\n comments,\n replyCounts,\n loading: commentsLoading,\n error: commentsError,\n refetch: refetchComments,\n } = useComments(selectedPost, feedDataOptions);\n\n const {\n messages: profileMessages,\n loading: profileLoading,\n error: profileError,\n refetch: refetchProfile,\n } = useProfile(profileAddress, { chainId, rpcUrl });\n\n // Aggregate profile messages by feed for Active On view\n const aggregatedFeeds = React.useMemo(\n () => aggregateByFeed(profileMessages),\n [profileMessages]\n );\n\n const handleRefresh = useCallback(() => {\n if (profileAddress) {\n refetchProfile();\n } else if (selectedPost) {\n refetchComments();\n } else if (selectedFeedName) {\n refetchPosts();\n } else {\n refetchFeeds();\n }\n }, [profileAddress, selectedPost, selectedFeedName, refetchProfile, refetchComments, refetchPosts, refetchFeeds]);\n\n const handleCompose = useCallback(() => {\n if (selectedFeedName) {\n setIsComposing(true);\n }\n }, [selectedFeedName]);\n\n const handleFilter = useCallback(() => {\n setIsFiltering(true);\n }, []);\n\n const handleSearch = useCallback(() => {\n setIsSearching(true);\n }, []);\n\n const handleShowHelp = useCallback(() => {\n setIsShowingHelp(true);\n }, []);\n\n const handleSelectFeed = useCallback((index: number) => {\n if (feeds[index]) {\n setSelectedFeedName(feeds[index].feedName);\n setSenderFilter(undefined);\n }\n }, [feeds]);\n\n const handleSelectPost = useCallback((index: number) => {\n if (posts[index]) {\n setSelectedPost(posts[index]);\n }\n }, [posts]);\n\n // We need refs to access current selection indices in callbacks\n const selectedPostIndexRef = React.useRef(0);\n const selectedCommentIndexRef = React.useRef(0);\n\n const handleViewProfile = useCallback(() => {\n // Get the address of the currently selected post or comment\n if (selectedPost) {\n // In comments view: index 0 = post, index 1+ = comments\n const index = selectedCommentIndexRef.current;\n if (index === 0) {\n // Post is selected\n setProfileAddress(selectedPost.sender);\n } else {\n // Comment is selected (actual comment index is index - 1)\n const commentIndex = index - 1;\n if (comments[commentIndex]) {\n setProfileAddress(comments[commentIndex].comment.sender);\n }\n }\n } else if (posts.length > 0) {\n // In posts view, use the selected post's author\n const postIndex = selectedPostIndexRef.current;\n if (posts[postIndex]) {\n setProfileAddress(posts[postIndex].sender);\n }\n }\n }, [selectedPost, posts, comments]);\n\n const handleSelectProfileItem = useCallback((index: number) => {\n if (index === 0) {\n // \"Their Feed\" option - navigate to posts view with feedName = profileAddress\n if (profileAddress) {\n setSelectedFeedName(profileAddress);\n setSenderFilter(undefined);\n setProfileAddress(null);\n }\n } else {\n // Active On feed (index - 1)\n const feedIndex = index - 1;\n if (aggregatedFeeds[feedIndex]) {\n const topic = aggregatedFeeds[feedIndex].topic;\n setSelectedFeedName(topic);\n setSenderFilter(profileAddress ?? undefined);\n setProfileAddress(null);\n }\n }\n }, [aggregatedFeeds, profileAddress]);\n\n const handleGoHome = useCallback(() => {\n setSelectedFeedName(null);\n setSelectedPost(null);\n setProfileAddress(null);\n setSenderFilter(undefined);\n }, []);\n\n // Toggle user filter: if filtered, clear it; if not, filter by selected post's author\n const handleToggleUserFilter = useCallback(() => {\n if (senderFilter) {\n // Clear the filter\n setSenderFilter(undefined);\n } else {\n // Filter by currently selected post's author\n const postIndex = selectedPostIndexRef.current;\n if (posts[postIndex]) {\n setSenderFilter(posts[postIndex].sender);\n }\n }\n }, [senderFilter, posts]);\n\n // Handle state restoration from navigation stack\n const handleRestoreState = useCallback((entry: NavEntry) => {\n setSelectedFeedName(entry.feedName);\n setSelectedPost(entry.post);\n setProfileAddress(entry.profileAddress);\n setSenderFilter(entry.senderFilter);\n }, []);\n\n // Profile items: 1 (Their Feed option) + aggregated feeds\n const profileItemsCount = 1 + aggregatedFeeds.length;\n\n const {\n viewMode,\n selectedFeedIndex,\n selectedPostIndex,\n selectedCommentIndex,\n selectedProfileIndex,\n setViewMode,\n goBack,\n } = useKeyboard({\n feedsCount: feeds.length,\n postsCount: posts.length,\n commentsCount: 1 + comments.length, // +1 for the post itself\n profileItemsCount,\n // Current context for stack snapshots\n currentFeedName: selectedFeedName,\n currentPost: selectedPost,\n currentProfileAddress: profileAddress,\n currentSenderFilter: senderFilter,\n // Callbacks\n onQuit: onExit,\n onRefresh: handleRefresh,\n onCompose: handleCompose,\n onFilter: handleFilter,\n onSearch: handleSearch,\n onSelectFeed: handleSelectFeed,\n onSelectPost: handleSelectPost,\n onViewProfile: handleViewProfile,\n onSelectProfileItem: handleSelectProfileItem,\n onGoHome: handleGoHome,\n onRestoreState: handleRestoreState,\n onToggleUserFilter: handleToggleUserFilter,\n onShowHelp: handleShowHelp,\n });\n\n // Keep refs in sync with current selection indices\n React.useEffect(() => {\n selectedPostIndexRef.current = selectedPostIndex;\n }, [selectedPostIndex]);\n\n React.useEffect(() => {\n selectedCommentIndexRef.current = selectedCommentIndex;\n }, [selectedCommentIndex]);\n\n\n // Reset states when going back (handled by stack now, but keep for safety)\n React.useEffect(() => {\n if (viewMode === \"feeds\") {\n setSelectedFeedName(null);\n setSelectedPost(null);\n setProfileAddress(null);\n } else if (viewMode === \"posts\") {\n setSelectedPost(null);\n }\n }, [viewMode]);\n\n const handleComposeSubmit = useCallback((text: string) => {\n // For now, just log - actual posting would require wallet integration\n console.log(`Would post to ${selectedFeedName}: ${text}`);\n setIsComposing(false);\n setViewMode(\"posts\");\n }, [selectedFeedName, setViewMode]);\n\n const handleComposeCancel = useCallback(() => {\n setIsComposing(false);\n setViewMode(\"posts\");\n }, [setViewMode]);\n\n const handleFilterSubmit = useCallback((address: string) => {\n setSenderFilter(address || undefined);\n setIsFiltering(false);\n setViewMode(\"posts\");\n }, [setViewMode]);\n\n const handleFilterCancel = useCallback(() => {\n setIsFiltering(false);\n setViewMode(\"posts\");\n }, [setViewMode]);\n\n const handleSearchSubmit = useCallback((feedName: string) => {\n setSelectedFeedName(feedName);\n setSenderFilter(undefined);\n setIsSearching(false);\n setViewMode(\"posts\");\n }, [setViewMode]);\n\n const handleSearchCancel = useCallback(() => {\n setIsSearching(false);\n goBack();\n }, [goBack]);\n\n const renderContent = () => {\n if (isShowingHelp) {\n return <Help onClose={() => setIsShowingHelp(false)} />;\n }\n\n if (isComposing && selectedFeedName) {\n return (\n <PostInput\n feedName={selectedFeedName}\n onSubmit={handleComposeSubmit}\n onCancel={handleComposeCancel}\n />\n );\n }\n\n if (isFiltering) {\n return (\n <SenderFilter\n onSubmit={handleFilterSubmit}\n onCancel={handleFilterCancel}\n />\n );\n }\n\n if (isSearching) {\n return (\n <FeedSearch\n onSubmit={handleSearchSubmit}\n onCancel={handleSearchCancel}\n />\n );\n }\n\n switch (viewMode) {\n case \"feeds\":\n return (\n <FeedList\n feeds={feeds}\n selectedIndex={selectedFeedIndex}\n loading={feedsLoading}\n error={feedsError}\n />\n );\n case \"posts\":\n return (\n <PostList\n feedName={selectedFeedName ?? \"\"}\n posts={posts}\n commentCounts={commentCounts}\n selectedIndex={selectedPostIndex}\n loading={postsLoading}\n error={postsError}\n />\n );\n case \"comments\":\n if (!selectedPost) {\n return null;\n }\n return (\n <CommentTree\n post={selectedPost}\n comments={comments}\n replyCounts={replyCounts}\n selectedIndex={selectedCommentIndex}\n loading={commentsLoading}\n error={commentsError}\n />\n );\n case \"profile\":\n if (!profileAddress) {\n return null;\n }\n return (\n <Profile\n address={profileAddress}\n activityMessages={profileMessages}\n loading={profileLoading}\n error={profileError}\n selectedIndex={selectedProfileIndex}\n />\n );\n default:\n return null;\n }\n };\n\n return (\n <Box flexDirection=\"column\" height={terminalHeight}>\n <Header\n viewMode={viewMode}\n chainId={chainId}\n feedName={selectedFeedName}\n senderFilter={senderFilter}\n profileAddress={profileAddress}\n />\n <Box flexGrow={1}>{renderContent()}</Box>\n <StatusBar viewMode={viewMode} />\n </Box>\n );\n}\n","import React from \"react\";\nimport { render } from \"ink\";\nimport { App } from \"./App\";\nimport { DEFAULT_CHAIN_ID } from \"../utils/config\";\n\ninterface TuiOptions {\n chainId?: number;\n rpcUrl?: string;\n}\n\n/**\n * Launch the interactive TUI\n */\nexport async function launchTui(options: TuiOptions): Promise<void> {\n const chainId = options.chainId ?? DEFAULT_CHAIN_ID;\n const rpcUrl = options.rpcUrl;\n\n // Clear screen before rendering TUI\n console.clear();\n\n const { waitUntilExit } = render(\n <App chainId={chainId} rpcUrl={rpcUrl} onExit={() => process.exit(0)} />\n );\n\n await waitUntilExit();\n}\n"]}
|