diff --git a/src/app.tsx b/src/app.tsx index 8207b33..165ebb4 100644 --- a/src/app.tsx +++ b/src/app.tsx @@ -49,6 +49,31 @@ import { ThreadScreen } from "@/screens/ThreadScreen"; const SPLASH_MIN_DISPLAY_MS = 500; +/** Generates header subtitle based on view type and item count */ +function getHeaderSubtitle( + view: View, + count: number, + hasMore: boolean +): string | undefined { + if (count <= 0) return undefined; + + // Only show "+" if we have a full page (30+) and there are more to load + const suffix = hasMore && count >= 30 ? "+" : ""; + + if (view === "notifications") { + return `${count} notifications`; + } + if (view === "bookmarks") { + return `${count}${suffix} bookmarked`; + } + return `${count} posts`; +} + +/** Capitalizes the first letter of a view name for display */ +function getViewTitle(view: View): string { + return view.charAt(0).toUpperCase() + view.slice(1); +} + export type View = | "timeline" | "bookmarks" @@ -782,16 +807,17 @@ function AppContent({ client, user }: AppProps) { ) : isMainView ? (
) : null} diff --git a/src/components/Header.tsx b/src/components/Header.tsx index dbf8c7c..368f5b2 100644 --- a/src/components/Header.tsx +++ b/src/components/Header.tsx @@ -1,35 +1,27 @@ -import type { View } from "@/app"; +import type { ReactNode } from "react"; import { colors } from "@/lib/colors"; interface HeaderProps { - currentView: View; - postCount?: number; - hasMore?: boolean; - unreadNotificationCount?: number; -} - -function getCountLabel(view: View, count: number, hasMore: boolean): string { - // Only show "+" if we have a full page (30+) and there are more to load - // If count < 30, we know we have all items regardless of hasMore - const suffix = hasMore && count >= 30 ? "+" : ""; - if (view === "notifications") { - return `${count} notifications`; - } - if (view === "bookmarks") { - return `${count}${suffix} bookmarked`; - } - return `${count} posts`; + /** The main title to display (e.g., "Timeline", "Bookmarks") */ + title: string; + /** Optional subtitle shown in parentheses (e.g., "30+ bookmarked") */ + subtitle?: string; + /** Optional badge count shown with bell icon (e.g., unread notifications) */ + badge?: number; + /** Optional content for the left slot (defaults to "xfeed" brand) */ + leftContent?: ReactNode; + /** Optional content for the right slot */ + rightContent?: ReactNode; } export function Header({ - currentView, - postCount, - hasMore = false, - unreadNotificationCount, + title, + subtitle, + badge, + leftContent, + rightContent, }: HeaderProps) { - const viewLabel = currentView.charAt(0).toUpperCase() + currentView.slice(1); - return ( - xfeed - {unreadNotificationCount !== undefined && unreadNotificationCount > 0 && ( - 🔔 {unreadNotificationCount} + {leftContent ?? xfeed} + {badge !== undefined && badge > 0 && ( + 🔔 {badge} )} | - {viewLabel} - {postCount !== undefined && postCount > 0 && ( - - {" "} - ({getCountLabel(currentView, postCount, hasMore)}) - - )} + {title} + {subtitle && ({subtitle})} + {rightContent} ); }