diff --git a/src/app/os/bin/page.tsx b/src/app/os/bin/page.tsx index 9a663f5..025eeac 100644 --- a/src/app/os/bin/page.tsx +++ b/src/app/os/bin/page.tsx @@ -104,72 +104,78 @@ export default function BinaryDetail() { (h) => h.os.build === build || `${h.os.version}_${h.os.build}` === build, ); + // Group versions by major version + const groupedHistory = useMemo(() => { + const groups: { [major: string]: typeof availableHistory } = {}; + for (const h of availableHistory) { + const major = h.os.version.split(".")[0]; + if (!groups[major]) groups[major] = []; + groups[major].push(h); + } + return Object.entries(groups).sort(([a], [b]) => Number(b) - Number(a)); + }, [availableHistory]); + + const renderVersionLink = (h: typeof availableHistory[0]) => { + const isCurrent = + h.os.build === build || `${h.os.version}_${h.os.build}` === build; + const isComparing = compareWith === `${h.os.version}_${h.os.build}`; + const versionTag = `${h.os.version}_${h.os.build}`; + + if (isCurrent) { + return ( + + {h.os.version} (current) + + ); + } + + const href = isComparing + ? addBasePath(`/os/bin?os=${encodeURIComponent(os!)}&path=${encodeURIComponent(path!)}`) + : addBasePath(`/os/bin?os=${encodeURIComponent(os!)}&path=${encodeURIComponent(path!)}&compare=${encodeURIComponent(versionTag)}`); + + return ( + + {h.os.version} + {isComparing && " (comparing)"} + + ); + }; + + const hasVersionHistory = availableHistory.length > 1; + return ( -
-
-
-
-

Entitlements of

-

- +

+ {/* Main content */} +
+
+
+

Entitlements

+

+ {path}

- {!loading && xml && }
- {availableHistory.length > 1 && ( -
-

Version History

-

- This binary exists in {availableHistory.length} OS versions. - Select a version to compare: -

-
- {availableHistory.map((h) => { - const isCurrent = - h.os.build === build || - `${h.os.version}_${h.os.build}` === build; - const isComparing = compareWith === `${h.os.version}_${h.os.build}`; - const versionTag = `${h.os.version}_${h.os.build}`; - - if (isCurrent) { - return ( - - {h.os.version} (current) - - ); - } - - const href = isComparing - ? addBasePath(`/os/bin?os=${encodeURIComponent(os!)}&path=${encodeURIComponent(path!)}`) - : addBasePath(`/os/bin?os=${encodeURIComponent(os!)}&path=${encodeURIComponent(path!)}&compare=${encodeURIComponent(versionTag)}`); - - return ( - - {h.os.version} - {isComparing && " (comparing)"} - - ); - })} -
+ {loading && ( +
+
+
)} - {loading &&

Loading...

} - {!loading && compareWith && compareError && (

Comparison failed

@@ -187,67 +193,113 @@ export default function BinaryDetail() { )} {!loading && !compareWith && xml && ( - { - function addLink(node: rendererNode) { - if (node.type === "text" && xmlKeys.has(node.value as string)) { - return { - type: "element", - tagName: "span", - children: [ - { - type: "element", - tagName: "a", - children: [ - { - type: "text", - value: node.value as string, - } as rendererNode, - ], - properties: { - className: ["text-blue-200", "hover:underline"], - href: addBasePath( - `/os/find?key=${encodeURIComponent( - node.value as string, - )}&os=${encodeURIComponent(os!)}`, - ), - }, - } as rendererNode, - ], - properties: { className: ["linked-key"] }, - } as rendererNode; +
+
+ +
+ { + function addLink(node: rendererNode) { + if (node.type === "text" && xmlKeys.has(node.value as string)) { + return { + type: "element", + tagName: "span", + children: [ + { + type: "element", + tagName: "a", + children: [ + { + type: "text", + value: node.value as string, + } as rendererNode, + ], + properties: { + className: ["text-blue-200", "hover:underline"], + href: addBasePath( + `/os/find?key=${encodeURIComponent( + node.value as string, + )}&os=${encodeURIComponent(os!)}`, + ), + }, + } as rendererNode, + ], + properties: { className: ["linked-key"] }, + } as rendererNode; + } + + if (node.children) { + node.children = node.children.map(addLink); + } + return node; } - if (node.children) { - node.children = node.children.map(addLink); - } - return node; - } - - return rows.map((row, i) => { - return createElement({ - node: addLink(row), - stylesheet, - useInlineStyles, - key: `code-segment-${i}`, + return rows.map((row, i) => { + return createElement({ + node: addLink(row), + stylesheet, + useInlineStyles, + key: `code-segment-${i}`, + }); }); - }); - }} - > - {xml} - + }} + > + {xml} + +
)} - {compareLoading &&

Loading comparison...

} + {compareLoading && ( +
+ )}
+ + {/* Version history sidebar */} + {hasVersionHistory && ( + + )}
); }