diff --git a/docs/app/[lang]/drivers/DriversClient.tsx b/docs/app/[lang]/drivers/DriversClient.tsx index b656302637..aea8d5180f 100644 --- a/docs/app/[lang]/drivers/DriversClient.tsx +++ b/docs/app/[lang]/drivers/DriversClient.tsx @@ -4,7 +4,7 @@ import { useEffect, useMemo, useRef, useState } from "react"; import { useParams } from "next/navigation"; import { LandingNav } from "@/components/landing/LandingNav"; import { LandingSelect } from "@/components/landing/LandingSelect"; -import { downloadLinksFor, formatSize, platformLabels, type AgentDownloadCatalog, type AgentRegistry, type DownloadSource, type JreDisplayEntry, type NativeAgentDisplayEntry, type OfflineBundleEntry } from "@/lib/agentRegistry"; +import { downloadLinksFor, formatSize, platformLabels, selectNativeAgentPlatform, type AgentDownloadCatalog, type AgentRegistry, type DownloadSource, type JreDisplayEntry, type NativeAgentDisplayEntry, type OfflineBundleEntry } from "@/lib/agentRegistry"; import { assembleCustomBundle, buildCustomBundleOptions, cnbMirrorUrl, computeBundlePlan, CUSTOM_BUNDLE_PLATFORMS, proxyUrl, resolveBundleJre, type BundleProgress } from "@/lib/agentBundle"; import { Archive, Cpu, Database, Download, ListChecks, Plug, Search, Terminal, X } from "lucide-react"; import { resolveLang, type DocsLang } from "@/lib/i18n"; @@ -223,6 +223,7 @@ export function DriversClient({ initialCatalog, initialRegistry }: { initialCata const [activeTab, setActiveTab] = useState("bundles"); const [searchQuery, setSearchQuery] = useState(""); const [selectedNativePlatforms, setSelectedNativePlatforms] = useState>({}); + const nativePlatformTouchedRef = useRef(new Set()); const [bundlePlatform, setBundlePlatform] = useState("windows-x64"); const [detectedPlatform, setDetectedPlatform] = useState(null); @@ -266,15 +267,15 @@ export function DriversClient({ initialCatalog, initialRegistry }: { initialCata const next = { ...current }; let changed = false; for (const group of nativeGroups) { - if (group.options.length === 0) continue; - if (!next[group.key] || !group.options.some((option) => option.platformKey === next[group.key])) { - next[group.key] = group.options[0].platformKey; + const platform = selectNativeAgentPlatform(group.options, detectedPlatform, next[group.key], nativePlatformTouchedRef.current.has(group.key)); + if (platform && platform !== next[group.key]) { + next[group.key] = platform; changed = true; } } return changed ? next : current; }); - }, [nativeGroups]); + }, [nativeGroups, detectedPlatform]); const filteredNativeGroups = useMemo( () => @@ -824,7 +825,10 @@ export function DriversClient({ initialCatalog, initialRegistry }: { initialCata ({ value: option.platformKey, label: option.platformLabel }))} - onChange={(platformKey) => setSelectedNativePlatforms((current) => ({ ...current, [group.key]: platformKey }))} + onChange={(platformKey) => { + nativePlatformTouchedRef.current.add(group.key); + setSelectedNativePlatforms((current) => ({ ...current, [group.key]: platformKey })); + }} ariaLabel={`${group.label}: ${t.platform}`} className="min-w-[190px] max-[760px]:w-full" /> @@ -864,6 +868,7 @@ export function DriversClient({ initialCatalog, initialRegistry }: { initialCata
{j.platformLabel} + {j.platformKey === detectedPlatform && {t.currentPlatform}} JRE {j.jreKey}
diff --git a/docs/lib/agentRegistry.test.ts b/docs/lib/agentRegistry.test.ts index a4ba2934a6..9b96a5d1d8 100644 --- a/docs/lib/agentRegistry.test.ts +++ b/docs/lib/agentRegistry.test.ts @@ -1,13 +1,40 @@ import assert from "node:assert/strict"; import { afterEach, test, vi } from "vitest"; import driverVersions from "../../agents/versions.json"; -import { buildAgentDownloadCatalog, buildDriverEntries, buildNativeAgentEntries, downloadLinksFor, formatSize } from "./agentRegistry"; +import { buildAgentDownloadCatalog, buildDriverEntries, buildNativeAgentEntries, downloadLinksFor, formatSize, selectNativeAgentPlatform } from "./agentRegistry"; import { fetchAgentDownloadCatalog } from "./agentRegistrySource"; afterEach(() => { vi.restoreAllMocks(); }); +const availablePlatforms = ["linux-aarch64", "linux-x64", "macos-aarch64", "macos-x64", "windows-aarch64", "windows-x64"].map((platformKey) => ({ platformKey })); + +for (const { platformKey } of availablePlatforms) { + test(`native Agent defaults to the detected ${platformKey} platform`, () => { + assert.equal(selectNativeAgentPlatform(availablePlatforms, platformKey), platformKey); + }); +} + +test("async ARM refinement updates the automatic default", () => { + const initial = selectNativeAgentPlatform(availablePlatforms, "macos-x64"); + assert.equal(selectNativeAgentPlatform(availablePlatforms, "macos-aarch64", initial), "macos-aarch64"); +}); + +test("async refinement preserves a platform selected manually for another machine", () => { + assert.equal(selectNativeAgentPlatform(availablePlatforms, "macos-aarch64", "windows-x64", true), "windows-x64"); + assert.equal(selectNativeAgentPlatform(availablePlatforms, "macos-aarch64", "macos-x64", true), "macos-x64"); +}); + +test("unsupported and unknown platforms fall back to an available artifact", () => { + const windowsOnly = [{ platformKey: "windows-x64" }]; + assert.equal(selectNativeAgentPlatform(windowsOnly, "macos-aarch64"), "windows-x64"); + assert.equal(selectNativeAgentPlatform(availablePlatforms, null), "linux-aarch64"); + assert.equal(selectNativeAgentPlatform(availablePlatforms, "unknown"), "linux-aarch64"); + assert.equal(selectNativeAgentPlatform(availablePlatforms, "windows-x64", "removed-platform", true), "windows-x64"); + assert.equal(selectNativeAgentPlatform([], "macos-aarch64"), undefined); +}); + test("offline download catalog includes the JDBC plugin ZIP", () => { const catalog = buildAgentDownloadCatalog([]); diff --git a/docs/lib/agentRegistry.ts b/docs/lib/agentRegistry.ts index 99ade8ad95..268a2a7301 100644 --- a/docs/lib/agentRegistry.ts +++ b/docs/lib/agentRegistry.ts @@ -74,6 +74,11 @@ export interface NativeAgentDisplayEntry { info: ArtifactInfo; } +export function selectNativeAgentPlatform(options: ReadonlyArray>, detectedPlatform: string | null, selectedPlatform?: string, manuallySelected = false): string | undefined { + if (manuallySelected && options.some((option) => option.platformKey === selectedPlatform)) return selectedPlatform; + return options.find((option) => option.platformKey === detectedPlatform)?.platformKey ?? options[0]?.platformKey; +} + export interface JdbcPluginDownloadEntry { label: string; filename: string; diff --git a/docs/screenshots/drivers-jre-platform-after.jpg b/docs/screenshots/drivers-jre-platform-after.jpg new file mode 100644 index 0000000000..02ae1a6bf6 Binary files /dev/null and b/docs/screenshots/drivers-jre-platform-after.jpg differ diff --git a/docs/screenshots/drivers-jre-platform-before.jpg b/docs/screenshots/drivers-jre-platform-before.jpg new file mode 100644 index 0000000000..10ae572997 Binary files /dev/null and b/docs/screenshots/drivers-jre-platform-before.jpg differ diff --git a/docs/screenshots/drivers-native-platform-after.jpg b/docs/screenshots/drivers-native-platform-after.jpg new file mode 100644 index 0000000000..e2421fdc42 Binary files /dev/null and b/docs/screenshots/drivers-native-platform-after.jpg differ diff --git a/docs/screenshots/drivers-native-platform-before.jpg b/docs/screenshots/drivers-native-platform-before.jpg new file mode 100644 index 0000000000..0e2975fda8 Binary files /dev/null and b/docs/screenshots/drivers-native-platform-before.jpg differ diff --git a/docs/screenshots/drivers-native-platform-mobile.jpg b/docs/screenshots/drivers-native-platform-mobile.jpg new file mode 100644 index 0000000000..ac0925dc6b Binary files /dev/null and b/docs/screenshots/drivers-native-platform-mobile.jpg differ