- Add global updateCheckEnabled setting to core schema/types and wire dashboard command to cache update checks in the CLI - Implement dashboard server update-check cache module plus REST routes for status and refresh behavior - Add dashboard client hook, legacy API helpers, and UpdateAvailableBanner UI to show cached CLI update notices - Cover update-check server routes, hook behavior, banner rendering, and route registration with focused tests - Document update-check configuration and API behavior in architecture and settings reference docs
64 lines
1.7 KiB
TypeScript
64 lines
1.7 KiB
TypeScript
import { useCallback, useEffect, useState } from "react";
|
|
import { checkForUpdate } from "../api";
|
|
|
|
const UPDATE_BANNER_DISMISSED_KEY = "kb-update-banner-dismissed";
|
|
|
|
export interface UseUpdateCheckResult {
|
|
updateAvailable: boolean;
|
|
latestVersion: string | null;
|
|
currentVersion: string | null;
|
|
loading: boolean;
|
|
dismissed: boolean;
|
|
dismiss: () => void;
|
|
}
|
|
|
|
export function useUpdateCheck(): UseUpdateCheckResult {
|
|
const [loading, setLoading] = useState(true);
|
|
const [updateAvailable, setUpdateAvailable] = useState(false);
|
|
const [latestVersion, setLatestVersion] = useState<string | null>(null);
|
|
const [currentVersion, setCurrentVersion] = useState<string | null>(null);
|
|
const [dismissed, setDismissed] = useState(false);
|
|
|
|
useEffect(() => {
|
|
const isDismissed = sessionStorage.getItem(UPDATE_BANNER_DISMISSED_KEY) === "true";
|
|
setDismissed(isDismissed);
|
|
|
|
let cancelled = false;
|
|
|
|
void checkForUpdate()
|
|
.then((result) => {
|
|
if (cancelled || result.disabled) return;
|
|
|
|
setUpdateAvailable(result.updateAvailable === true);
|
|
setLatestVersion(typeof result.latestVersion === "string" ? result.latestVersion : null);
|
|
setCurrentVersion(typeof result.currentVersion === "string" ? result.currentVersion : null);
|
|
})
|
|
.catch(() => {
|
|
// Fail silently. Update checks are best-effort.
|
|
})
|
|
.finally(() => {
|
|
if (!cancelled) {
|
|
setLoading(false);
|
|
}
|
|
});
|
|
|
|
return () => {
|
|
cancelled = true;
|
|
};
|
|
}, []);
|
|
|
|
const dismiss = useCallback(() => {
|
|
setDismissed(true);
|
|
sessionStorage.setItem(UPDATE_BANNER_DISMISSED_KEY, "true");
|
|
}, []);
|
|
|
|
return {
|
|
updateAvailable,
|
|
latestVersion,
|
|
currentVersion,
|
|
loading,
|
|
dismissed,
|
|
dismiss,
|
|
};
|
|
}
|