import { createEffect, createSignal, createRoot } from "solid-js" import type { LatestReleaseInfo, WorkspaceEventPayload } from "../../../server/src/api-types" import { getServerMeta } from "../lib/server-meta" import { serverEvents } from "../lib/server-events" import { showToastNotification, ToastHandle } from "../lib/notifications" import { getLogger } from "../lib/logger" import { hasInstances, showFolderSelection } from "./ui" const log = getLogger("actions") const [availableRelease, setAvailableRelease] = createSignal(null) let initialized = false let visibilityEffectInitialized = false let activeToast: ToastHandle | null = null let activeToastVersion: string | null = null function dismissActiveToast() { if (activeToast) { activeToast.dismiss() activeToast = null activeToastVersion = null } } function ensureVisibilityEffect() { if (visibilityEffectInitialized) { return } visibilityEffectInitialized = true // Use createRoot to properly scope this effect createRoot(() => { createEffect(() => { const release = availableRelease() const shouldShow = Boolean(release) && (!hasInstances() || showFolderSelection()) if (!shouldShow || !release) { dismissActiveToast() return } if (!activeToast || activeToastVersion !== release.version) { dismissActiveToast() activeToast = showToastNotification({ title: `NomadArch ${release.version}`, message: release.channel === "dev" ? "Dev release build available." : "New stable build on GitHub.", variant: "info", duration: Number.POSITIVE_INFINITY, position: "bottom-right", action: { label: "View release", href: release.url, }, }) activeToastVersion = release.version } }) }) } export function initReleaseNotifications() { if (initialized) { return } initialized = true ensureVisibilityEffect() void refreshFromMeta() serverEvents.on("app.releaseAvailable", (event) => { const typedEvent = event as Extract applyRelease(typedEvent.release) }) } async function refreshFromMeta() { try { const meta = await getServerMeta(true) if (meta.latestRelease) { applyRelease(meta.latestRelease) } } catch (error) { log.warn("Unable to load server metadata for release info", error) } } function applyRelease(release: LatestReleaseInfo | null | undefined) { if (!release) { setAvailableRelease(null) return } setAvailableRelease(release) } export function useAvailableRelease() { return availableRelease }