/// // dont forget to run this // npx @tanstack/router-cli generate import type { QueryClient } from "@tanstack/react-query"; import { createRootRouteWithContext, Link, // Link, // Outlet, Scripts, useLocation, useNavigate, } from "@tanstack/react-router"; import { TanStackRouterDevtools } from "@tanstack/react-router-devtools"; import { useAtom } from "jotai"; import * as React from "react"; import { toast as sonnerToast } from "sonner"; import { Toaster } from "sonner"; import { KeepAliveOutlet, KeepAliveProvider } from "tanstack-router-keepalive"; import { HOST_ADMIN, HOST_DESCRIPTION, HOST_HERO, HOST_LOGIN_BLURB, HOST_MAIN_TITLE, HOST_SIGNUP_PDS, HOST_SUB_TITLE, HOST_TITLE, HOST_UNAUTHED_DEFAULT_FEEDS } from "~/../policy"; import { Composer } from "~/components/Composer"; import { DefaultCatchBoundary } from "~/components/DefaultCatchBoundary"; import { Import } from "~/components/Import"; //import Login from "~/components/Login"; import Logo from "~/components/LogoSvg"; //import { ModerationBatcher } from "~/components/ModerationBatcher"; //import { ModerationInitializer } from "~/components/ModerationInitializer"; import { NotFound } from "~/components/NotFound"; import { AutoLabelProvider } from "~/providers/AutoLabelProvider"; import { LikeMutationQueueProvider } from "~/providers/LikeMutationQueueProvider"; import { PollMutationQueueProvider } from "~/providers/PollMutationQueueProvider"; import { UnifiedAuthProvider, useAuth } from "~/providers/UnifiedAuthProvider"; import { FeedTabOnTop } from "~/routes/index"; import { composerAtom, hueAtom, imgCDNAtom, quickAuthAtom, useAtomCssVar } from "~/utils/atoms"; import { seo } from "~/utils/seo"; import { useQueryIdentity, useQueryPreferences, useQueryProfile } from "~/utils/useQuery"; export const Route = createRootRouteWithContext<{ queryClient: QueryClient; }>()({ head: () => ({ meta: [ { charSet: "utf-8", }, { name: "viewport", content: "width=device-width, initial-scale=1", }, ...seo({ title: HOST_TITLE, description: `Distributed Bluesky Client`, }), ], links: [ { rel: "apple-touch-icon", sizes: "180x180", href: "/apple-touch-icon.png", }, { rel: "icon", type: "image/png", sizes: "32x32", href: "/redstar.png?whatwg", }, { rel: "icon", type: "image/png", sizes: "16x16", href: "/redstar.png?whatwg", }, { rel: "manifest", href: "/site.webmanifest", color: "#fffff" }, { rel: "icon", href: "/favicon.ico" }, ], }), errorComponent: import.meta.env.DEV ? undefined : (props) => ( ), notFoundComponent: () => , component: RootComponent, }); function RootComponent() { return ( {/* */} ); } export function AppToaster() { return ( ); } export function renderSnack({ title, description, button, }: Omit) { return sonnerToast.custom((id) => ( { button?.onClick?.(); }, } : undefined } /> )); } function Snack(props: ToastProps) { const { title, description, button, id } = props; return (

{title}

{description ? (

{description}

) : null}
{button ? (
) : null}
); } /* Types */ interface ToastProps { id: string | number; title: string; description?: string; button?: { label: string; onClick: () => void; }; } function RootDocument({ children }: { children: React.ReactNode }) { useAtomCssVar(hueAtom, "--tw-gray-hue"); const location = useLocation(); const navigate = useNavigate(); const { agent } = useAuth(); const isNotifications = location.pathname.startsWith("/notifications"); const authed = !!agent?.did; const isProfile = agent && (location.pathname === `/profile/${agent?.did}` || location.pathname === `/profile/${encodeURIComponent(agent?.did ?? "")}`); const isSettings = location.pathname.startsWith("/settings"); const isSearch = location.pathname.startsWith("/search"); const isFeeds = location.pathname.startsWith("/feeds"); const isModeration = location.pathname.startsWith("/moderation"); const isAbout = location.pathname.startsWith("/about"); const locationEnum: | "feeds" | "search" | "settings" | "notifications" | "profile" | "moderation" | "about" | "home" = isFeeds ? "feeds" : isSearch ? "search" : isSettings ? "settings" : isNotifications ? "notifications" : isProfile ? "profile" : isModeration ? "moderation" : isAbout ? "about" : "home"; const [, setComposerPost] = useAtom(composerAtom); return ( <>
{agent?.did && ( )}
{children}
{agent?.did ? ( ) : (
{HOST_MAIN_TITLE} {HOST_SUB_TITLE && ( {HOST_SUB_TITLE} ) }
{/* */} Log in
)} ); } export function MaterialNavItem({ visible = true, InactiveIcon, ActiveIcon, text, active, onClickCallbback, small, }: { visible?: boolean; InactiveIcon: React.ReactElement; ActiveIcon: React.ReactElement; text: string; active: boolean; onClickCallbback: () => void; small?: boolean | string; }) { if (!visible) return null if (small) return ( ); return ( ); } function MaterialPillButton({ InactiveIcon, ActiveIcon, text, //active, onClickCallbback, small, }: { InactiveIcon: React.ReactElement; ActiveIcon: React.ReactElement; text: string; //active: boolean; onClickCallbback: () => void; small?: boolean | string; }) { const active = false; return ( ); } export const ProfileSmall = ({ did, large = false, }: { did: string, large?: boolean; }) => { const navigate = useNavigate(); const { data: identity } = useQueryIdentity(did); const { data: profiledata } = useQueryProfile( `at://${did}/app.bsky.actor.profile/self` ); const profile = profiledata?.value; const [imgcdn] = useAtom(imgCDNAtom) function getAvatarUrl(p: typeof profile) { const link = p?.avatar?.ref?.["$link"]; if (!link || !did) return null; return `https://${imgcdn}/img/avatar/plain/${did}/${link}@jpeg`; } const onProfileClick = (e: React.MouseEvent) => { e.stopPropagation(); navigate({ to: "/profile/$did", params: { did: did }, }); } if (!profiledata) { return ( // Skeleton loader
); } return (
avatar
{profile?.displayName}
@{identity?.handle}
); }; function FeedListDesktopSidebar() { const { agent, status } = useAuth(); const [quickAuth] = useAtom(quickAuthAtom); const isAuthRestoring = quickAuth ? status === "loading" : false; const identityresultmaybe = useQueryIdentity( !isAuthRestoring ? agent?.did : undefined, ); const identity = identityresultmaybe?.data; const prefsresultmaybe = useQueryPreferences({ agent: !isAuthRestoring ? (agent ?? undefined) : undefined, pdsUrl: !isAuthRestoring ? identity?.pds : undefined, }); const prefs = prefsresultmaybe?.data; const savedFeeds = React.useMemo(() => { const savedFeedsPref = prefs?.preferences?.find( (p: any) => p?.$type === "app.bsky.actor.defs#savedFeedsPrefV2", ); return savedFeedsPref?.items || []; }, [prefs]); const pinnedFeeds = React.useMemo(() => { return savedFeeds.filter((feed: any) => feed.pinned); }, [savedFeeds]); const shimmedunautheddefault = HOST_UNAUTHED_DEFAULT_FEEDS.map((aturi: string, idx: number) => { return { value: aturi, pinned: true, } }) const feedsmap = agent?.did ? pinnedFeeds : shimmedunautheddefault; return (
{feedsmap.map((item: any, idx: number) => { return })}
) } function LoginRedirect() { const location = useLocation(); const dontShowLoginButton = location.pathname === "/settings" return (
{HOST_LOGIN_BLURB}
{!dontShowLoginButton && ( Log in )} {HOST_SIGNUP_PDS && ( // todo make signup actually work )}
) }