96 lines · 3.3 KB · TypeScript
RawDownload
import type { EnvironmentId, ScopedThreadRef } from "@t3tools/contracts";import { Globe, History, RadioTower } from "lucide-react"; import type { BrowserHistoryEntry } from "~/browserHistoryStore";import { Empty, EmptyDescription, EmptyMedia, EmptyTitle } from "~/components/ui/empty";import { DiscoveryList } from "../ui/discovery-list"; import { PreviewLocalServerCard } from "./PreviewLocalServerCard";import { PreviewRecentUrlCard } from "./PreviewRecentUrlCard";import { useDiscoveredLocalServers } from "./useDiscoveredLocalServers"; interface Props {  threadRef: ScopedThreadRef;  environmentId: EnvironmentId;  configuredUrls?: ReadonlyArray<string> | undefined;  recentEntries: ReadonlyArray<BrowserHistoryEntry>;  onRemoveRecent: (url: string) => void;  onOpenUrl: (url: string) => void;} export function PreviewEmptyState({  threadRef,  environmentId,  configuredUrls,  recentEntries,  onRemoveRecent,  onOpenUrl,}: Props) {  const servers = useDiscoveredLocalServers({    environmentId,    configuredUrls,  });  const recents = recentEntries.filter((entry) => URL.canParse(entry.url)).slice(0, 8);   if (servers.length === 0 && recents.length === 0) {    return (      <Empty>        <EmptyMedia variant="icon">          <Globe className="size-4.5 text-muted-foreground" />        </EmptyMedia>        <EmptyTitle>No preview yet</EmptyTitle>        <EmptyDescription>          Type a URL above, or run a dev script. Browser-ready localhost servers will show up here          automatically.        </EmptyDescription>      </Empty>    );  }   return (    <div className="flex h-full min-h-0 overflow-y-auto px-5 py-8">      <div className="mx-auto flex w-full max-w-xl flex-col gap-6">        {recents.length > 0 ? (          <div className="flex flex-col gap-3">            <div className="flex items-center gap-2 text-sm text-muted-foreground">              <History className="size-4 shrink-0" />              <h2 className="font-medium">Recently used</h2>            </div>            <DiscoveryList>              {recents.map((entry) => (                <PreviewRecentUrlCard                  key={entry.url}                  threadRef={threadRef}                  entry={entry}                  onOpen={() => onOpenUrl(entry.url)}                  onRemove={() => onRemoveRecent(entry.url)}                />              ))}            </DiscoveryList>          </div>        ) : null}        {servers.length > 0 ? (          <div className="flex flex-col gap-3">            <div className="flex items-center gap-2 text-sm text-muted-foreground">              <RadioTower className="size-4 shrink-0" />              <h2 className="font-medium">Local servers</h2>            </div>            <DiscoveryList>              {servers.map((server) => (                <PreviewLocalServerCard                  key={`${server.host}:${server.port}`}                  threadRef={threadRef}                  server={server}                  onOpen={() => onOpenUrl(server.requestedUrl)}                />              ))}            </DiscoveryList>            <p className="px-1 text-xs text-muted-foreground">              Select a live local server to open it in this browser tab.            </p>          </div>        ) : null}      </div>    </div>  );}