60 lines
1.8 KiB
TypeScript
60 lines
1.8 KiB
TypeScript
import { useEffect, useState } from "react";
|
||
import { getBackendMeta } from "../../api";
|
||
import { FRONTEND_VERSION } from "../../frontendVersion";
|
||
import { readCachedBackendVersion, writeCachedBackendVersion } from "../../lib/backendVersionCache";
|
||
|
||
function isAbortError(error: unknown): boolean {
|
||
return (
|
||
(error instanceof DOMException && error.name === "AbortError") ||
|
||
(error instanceof Error && error.name === "AbortError")
|
||
);
|
||
}
|
||
|
||
export function AppShellFooter(): JSX.Element {
|
||
const [backendVersion, setBackendVersion] = useState<string | null>(() => readCachedBackendVersion());
|
||
|
||
useEffect(() => {
|
||
const ac = new AbortController();
|
||
void getBackendMeta({ signal: ac.signal })
|
||
.then((meta) => {
|
||
if (ac.signal.aborted) {
|
||
return;
|
||
}
|
||
const v = meta.version;
|
||
const label = typeof v === "string" && v.length > 0 ? v : "не указана";
|
||
writeCachedBackendVersion(label);
|
||
setBackendVersion(label);
|
||
})
|
||
.catch((err) => {
|
||
if (ac.signal.aborted || isAbortError(err)) {
|
||
return;
|
||
}
|
||
setBackendVersion((prev) => {
|
||
const cached = readCachedBackendVersion();
|
||
if (cached) {
|
||
return cached;
|
||
}
|
||
if (prev !== null) {
|
||
return prev;
|
||
}
|
||
return "недоступна";
|
||
});
|
||
});
|
||
return () => ac.abort();
|
||
}, []);
|
||
|
||
const backendLabel = backendVersion === null ? "…" : backendVersion;
|
||
|
||
return (
|
||
<footer className="app-shell__footer">
|
||
<p className="app-shell__footer-versions">
|
||
Версия клиента: {FRONTEND_VERSION}
|
||
<span className="app-shell__footer-sep" aria-hidden="true">
|
||
{" · "}
|
||
</span>
|
||
Версия сервера: {backendLabel}
|
||
</p>
|
||
</footer>
|
||
);
|
||
}
|