Skip to content

Commit 79affd7

Browse files
committed
feat(web): tick timeAgo via shared clock in TopbarProvider
1 parent 6b878c7 commit 79affd7

2 files changed

Lines changed: 14 additions & 5 deletions

File tree

apps/web/src/components/console/overview-topbar.tsx

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,8 @@ function formatBlock(n: number) {
1313
return `#${n.toLocaleString()}`;
1414
}
1515

16-
function timeAgo(iso: string) {
17-
const diff = Math.floor((Date.now() - new Date(iso).getTime()) / 1000);
16+
function timeAgo(iso: string, now: number) {
17+
const diff = Math.floor((now - new Date(iso).getTime()) / 1000);
1818
if (diff < 60) return "just now";
1919
if (diff < 3600) return `${Math.floor(diff / 60)} min ago`;
2020
if (diff < 86400) return `${Math.floor(diff / 3600)}h ago`;
@@ -106,17 +106,17 @@ export function OverviewTopbar({
106106
lastUpdated,
107107
}: OverviewTopbarProps) {
108108
const { data: status } = useStatus();
109-
const { autoRefresh, setAutoRefresh, autoRefreshLabel } = useTopbar();
109+
const { autoRefresh, setAutoRefresh, autoRefreshLabel, now } = useTopbar();
110110

111111
const blockHeight = status?.chainTip ? formatBlock(status.chainTip) : "—";
112112

113113
let lastUpdatedDisplay: string;
114114
if (lastUpdated === null) {
115115
lastUpdatedDisplay = "—";
116116
} else if (lastUpdated !== undefined) {
117-
lastUpdatedDisplay = timeAgo(lastUpdated);
117+
lastUpdatedDisplay = timeAgo(lastUpdated, now);
118118
} else {
119-
lastUpdatedDisplay = status?.timestamp ? timeAgo(status.timestamp) : "—";
119+
lastUpdatedDisplay = status?.timestamp ? timeAgo(status.timestamp, now) : "—";
120120
}
121121

122122
return (

apps/web/src/lib/topbar-context.tsx

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,12 +16,14 @@ interface TopbarState {
1616
autoRefresh: RefreshInterval;
1717
setAutoRefresh: (v: RefreshInterval) => void;
1818
autoRefreshLabel: string;
19+
now: number;
1920
}
2021

2122
const TopbarCtx = createContext<TopbarState>({
2223
autoRefresh: null,
2324
setAutoRefresh: () => {},
2425
autoRefreshLabel: "Auto-refresh off",
26+
now: Date.now(),
2527
});
2628

2729
export function useTopbar() {
@@ -30,6 +32,7 @@ export function useTopbar() {
3032

3133
export function TopbarProvider({ children }: { children: React.ReactNode }) {
3234
const [autoRefresh, setAutoRefresh] = useState<RefreshInterval>(null);
35+
const [now, setNow] = useState(() => Date.now());
3336
const queryClient = useQueryClient();
3437
const intervalRef = useRef<ReturnType<typeof setInterval> | null>(null);
3538

@@ -45,6 +48,11 @@ export function TopbarProvider({ children }: { children: React.ReactNode }) {
4548
};
4649
}, [autoRefresh, queryClient]);
4750

51+
useEffect(() => {
52+
const id = setInterval(() => setNow(Date.now()), 60_000);
53+
return () => clearInterval(id);
54+
}, []);
55+
4856
const refreshLabel = REFRESH_OPTIONS.find((o) => o.value === autoRefresh)?.label ?? "Auto-refresh off";
4957

5058
return (
@@ -53,6 +61,7 @@ export function TopbarProvider({ children }: { children: React.ReactNode }) {
5361
autoRefresh,
5462
setAutoRefresh,
5563
autoRefreshLabel: refreshLabel,
64+
now,
5665
}}
5766
>
5867
{children}

0 commit comments

Comments
 (0)