diff --git a/src/App.tsx b/src/App.tsx index 5c5e734..c83ba68 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -8,7 +8,9 @@ import { Skeleton } from "@/components/ui/skeleton" import { api, groupsOf, useNodes, type Node } from "@/lib/api" import { loadConfig } from "@/lib/config" -type Me = { authed: boolean; github: boolean; site_name: string; public_page: boolean } +// `history_days` is absent from hubs predating the hourly tier, which kept a +// week for anonymous callers. +type Me = { authed: boolean; github: boolean; site_name: string; public_page: boolean; history_days?: number } // Split out because recharts is most of this bundle and the list page draws no // chart. The landing page is 242 kB rather than 629 kB (77 kB gzipped against @@ -181,7 +183,7 @@ export default function App() { ) : selected ? ( }> - + ) : (

diff --git a/src/components/NodeDetail.tsx b/src/components/NodeDetail.tsx index 21d3d02..35c88ad 100644 --- a/src/components/NodeDetail.tsx +++ b/src/components/NodeDetail.tsx @@ -10,7 +10,7 @@ import { Country, Status } from "@/components/NodeCard" import { api, type Node } from "@/lib/api" import { axisBytes, axisTop, bytes, clockFor, cycle, despike, quarters, cpuName, FOREVER, money, osName, rate, - timeTicks, + tickClock, timeTicks, windows, } from "@/lib/format" type Point = { @@ -47,18 +47,6 @@ type Probes = Record */ type Loss = Record -const RANGES = [ - { hours: 1, label: "1 小时" }, - { hours: 6, label: "6 小时" }, - { hours: 24, label: "24 小时" }, - { hours: 168, label: "7 天" }, -] - -// Latency stops at a day. A week-wide bucket would still carry the spread and the -// loss figure, but a week of probe history is outside this page's purpose, and -// these are the windows in which every ping remains on the chart. -const RANGES_FOR = { resources: RANGES, latency: RANGES.filter((r) => r.hours <= 24) } - const AXIS = { stroke: "currentColor", fontSize: 11, tickLine: false, axisLine: false } // No grow-in animation: it would spend 1.5 s drawing a line across the panel on @@ -100,11 +88,18 @@ function Panel({ title, children }: { title: string; children: React.ReactNode } ) } -function Tab({ active, onClick, children }: { active: boolean; onClick: () => void; children: string }) { +// `narrow` tightens the padding on a phone, so the seven windows of a year of +// history fit one row of a 360px screen. +function Tab({ active, onClick, narrow = false, children }: { + active: boolean + onClick: () => void + narrow?: boolean + children: string +}) { return (