import { LuRefreshCcw } from "react-icons/lu"; import { useCallback, useEffect, useState } from "react"; import { Button } from "@components/Button"; import { GridCard } from "@components/Card"; import { PublicIP } from "@hooks/stores"; import { m } from "@localizations/messages.js"; import { JsonRpcResponse, useJsonRpc } from "@hooks/useJsonRpc"; import notifications from "@/notifications"; import { formatters } from "@/utils"; const TimeAgoLabel = ({ date }: { date: Date }) => { const [timeAgo, setTimeAgo] = useState(formatters.timeAgo(date)); useEffect(() => { const interval = setInterval(() => { setTimeAgo(formatters.timeAgo(date)); }, 1000); return () => clearInterval(interval); }, [date]); return ( {timeAgo} ); }; export default function PublicIPCard() { const { send } = useJsonRpc(); const [publicIPs, setPublicIPs] = useState([]); const refreshPublicIPs = useCallback(() => { send("getPublicIPAddresses", { refresh: true }, (resp: JsonRpcResponse) => { setPublicIPs([]); if ("error" in resp) { notifications.error(m.public_ip_card_refresh_error({ error: resp.error.data || m.unknown_error() })); return; } const publicIPs = resp.result as PublicIP[]; // sort the public IPs by IP address // IPv6 addresses are sorted after IPv4 addresses setPublicIPs(publicIPs.sort(({ ip: aIp }, { ip: bIp }) => { const aIsIPv6 = aIp.includes(":"); const bIsIPv6 = bIp.includes(":"); if (aIsIPv6 && !bIsIPv6) return 1; if (!aIsIPv6 && bIsIPv6) return -1; return aIp.localeCompare(bIp); })); }); }, [send, setPublicIPs]); useEffect(() => { refreshPublicIPs(); }, [refreshPublicIPs]); return (

{m.public_ip_card_header()}

{publicIPs.length === 0 ? (
) : (
{publicIPs?.map(ip => (
{ip.ip} {ip.last_updated && }
))}
)}
); }