main
ts 90 lines 2.39 KB
Raw
1 import { useEffect, useMemo, useState } from "react";
2 import { useList, type BaseServer } from "@/hooks/useList";
3 import { apiClient } from "@/lib/apiClient";
4 import { BROWSER_API_PATHS } from "@/lib/apiPaths";
5 import {
6 parseLeaseMetadata,
7 resolveLeasePayment,
8 resolveLeaseThumbnail,
9 } from "@/lib/metadata";
10 import type { Lease, PublicStateResponse } from "@/types/api";
11
12 type PublicState = {
13 leases: Lease[];
14 landingPageEnabled: boolean;
15 };
16
17 function convertPublicLeasesToServers(leases: Lease[]): BaseServer[] {
18 return leases.map((row) => {
19 const metadata = parseLeaseMetadata(row.metadata);
20 const payment = resolveLeasePayment(metadata);
21 const hostname = row.hostname || "";
22 const serviceName = row.name || "";
23
24 return {
25 id: hostname,
26 name: serviceName || hostname || "(unnamed)",
27 description: metadata.description || "",
28 tags: metadata.tags,
29 thumbnail: resolveLeaseThumbnail(metadata, hostname),
30 owner: metadata.owner || "",
31 online: (row.ready || 0) > 0,
32 dns: hostname,
33 link: hostname ? `https://${hostname}/` : "",
34 lastUpdated: row.last_seen_at || undefined,
35 firstSeen: row.first_seen_at || undefined,
36 paymentEnabled: payment.enabled,
37 paymentLabel: payment.label,
38 };
39 });
40 }
41
42 export function useServerList() {
43 const [publicState, setPublicState] = useState<PublicState>({
44 leases: [],
45 landingPageEnabled: false,
46 });
47
48 useEffect(() => {
49 let cancelled = false;
50
51 void (async () => {
52 try {
53 const data = await apiClient.get<PublicStateResponse>(
54 BROWSER_API_PATHS.public.state
55 );
56 if (cancelled) {
57 return;
58 }
59 setPublicState({
60 leases: Array.isArray(data?.leases) ? data.leases : [],
61 landingPageEnabled: data?.landing_page_enabled ?? false,
62 });
63 } catch (error) {
64 console.error("Failed to load public relay state", error);
65 if (!cancelled) {
66 setPublicState({ leases: [], landingPageEnabled: false });
67 }
68 }
69 })();
70
71 return () => {
72 cancelled = true;
73 };
74 }, []);
75
76 const servers: BaseServer[] = useMemo(
77 () => convertPublicLeasesToServers(publicState.leases),
78 [publicState.leases]
79 );
80
81 const list = useList({
82 servers,
83 storageKey: "serverFavorites",
84 });
85
86 return {
87 ...list,
88 landingPageEnabled: publicState.landingPageEnabled,
89 };
90 }