feat(node): package Ubuntu desktop setup and trusted access

This commit is contained in:
DCCONSTRUCTIONS
2026-09-05 17:27:59 +03:00
parent 57f2537af3
commit d696842f5d
52 changed files with 4457 additions and 0 deletions
+28
View File
@@ -0,0 +1,28 @@
import { useCallback, useEffect, useState } from "react";
import { type ToastItem } from "@nodedc/ui-react";
import { APIError, loginFromLaunch, request, type Status } from "./api";
export function useNode() {
const [value, setValue] = useState<Status | null>(null);
const [pending, setPending] = useState(true);
const [locked, setLocked] = useState(false);
const [toasts, setToasts] = useState<ToastItem[]>([]);
const failure = useCallback((error: unknown) => {
if (error instanceof APIError && error.status === 401) { setValue(null); setLocked(true); }
setToasts([{ id: "request", tone: "error", title: error instanceof Error ? error.message : "Нода недоступна", durationMs: null }]);
}, []);
const refresh = useCallback(async () => {
setPending(true);
try { const result = await request<Status>("/api/status"); setValue(result); setLocked(false); setToasts([]); }
catch (error) { failure(error); }
finally { setPending(false); }
}, [failure]);
useEffect(() => {
const launch = () => { void loginFromLaunch().then(refresh).catch(error => { failure(error); setPending(false); }); };
launch(); window.addEventListener("hashchange", launch);
return () => window.removeEventListener("hashchange", launch);
}, [refresh, failure]);
const success = useCallback((title: string) => setToasts([{ id: "request", tone: "success", title }]), []);
return { value, pending, locked, refresh, failure, success, toasts,
dismiss: (id: string) => setToasts(items => items.filter(item => item.id !== id)) };
}