mirror of
https://github.com/Xevion/dynamic-preauth.git
synced 2025-12-18 14:11:48 -06:00
feat(frontend): add platform icons and improve download button UX
Replace generic download icon with platform-specific icons (Windows, macOS, Linux) using react-icons. Show detected platform name in the main download button text and disable auto-download when platform cannot be detected, requiring manual selection from dropdown instead.
This commit is contained in:
@@ -22,6 +22,7 @@
|
||||
"clsx": "^2.1.1",
|
||||
"react": "^19.0.0",
|
||||
"react-dom": "^19.0.0",
|
||||
"react-icons": "^5.5.0",
|
||||
"react-tooltip": "^5.28.0",
|
||||
"react-use-websocket": "^4.11.1",
|
||||
"tailwind-merge": "^2.5.5",
|
||||
|
||||
12
frontend/pnpm-lock.yaml
generated
12
frontend/pnpm-lock.yaml
generated
@@ -47,6 +47,9 @@ importers:
|
||||
react-dom:
|
||||
specifier: ^19.0.0
|
||||
version: 19.0.0(react@19.0.0)
|
||||
react-icons:
|
||||
specifier: ^5.5.0
|
||||
version: 5.5.0(react@19.0.0)
|
||||
react-tooltip:
|
||||
specifier: ^5.28.0
|
||||
version: 5.28.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
|
||||
@@ -2086,6 +2089,11 @@ packages:
|
||||
peerDependencies:
|
||||
react: ^19.0.0
|
||||
|
||||
react-icons@5.5.0:
|
||||
resolution: {integrity: sha512-MEFcXdkP3dLo8uumGI5xN3lDFNsRtrjbOEKDLD7yv76v4wpnEq2Lt2qeHaQOr34I/wPN3s3+N08WkQ+CW37Xiw==}
|
||||
peerDependencies:
|
||||
react: '*'
|
||||
|
||||
react-refresh@0.14.2:
|
||||
resolution: {integrity: sha512-jCvmsr+1IUSMUyzOkRcvnVbX3ZYC6g9TDrDbFuFmRDq7PD4yaGbLKNQL6k2jnArV8hjYxh7hVhAZB6s9HDGpZA==}
|
||||
engines: {node: '>=0.10.0'}
|
||||
@@ -5086,6 +5094,10 @@ snapshots:
|
||||
react: 19.0.0
|
||||
scheduler: 0.25.0
|
||||
|
||||
react-icons@5.5.0(react@19.0.0):
|
||||
dependencies:
|
||||
react: 19.0.0
|
||||
|
||||
react-refresh@0.14.2: {}
|
||||
|
||||
react-tooltip@5.28.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0):
|
||||
|
||||
@@ -9,10 +9,10 @@ import {
|
||||
MenuSeparator,
|
||||
} from "@headlessui/react";
|
||||
import {
|
||||
ArrowDownTrayIcon,
|
||||
BeakerIcon,
|
||||
ChevronDownIcon,
|
||||
} from "@heroicons/react/16/solid";
|
||||
import { FaWindows, FaApple, FaLinux } from "react-icons/fa";
|
||||
import { useRef } from "react";
|
||||
|
||||
type DownloadButtonProps = {
|
||||
@@ -36,6 +36,34 @@ function getSystemType(): SystemType | null {
|
||||
}
|
||||
}
|
||||
|
||||
function getPlatformIcon(id: string, className?: string) {
|
||||
const platformId = id.toLowerCase();
|
||||
switch (platformId) {
|
||||
case "windows":
|
||||
return <FaWindows className={className} />;
|
||||
case "macos":
|
||||
return <FaApple className={className} />;
|
||||
case "linux":
|
||||
return <FaLinux className={className} />;
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
function getPlatformDisplayName(id: string): string {
|
||||
const platformId = id.toLowerCase();
|
||||
switch (platformId) {
|
||||
case "windows":
|
||||
return "Windows";
|
||||
case "macos":
|
||||
return "macOS";
|
||||
case "linux":
|
||||
return "Linux";
|
||||
default:
|
||||
return id;
|
||||
}
|
||||
}
|
||||
|
||||
export default function DownloadButton({
|
||||
disabled,
|
||||
executables,
|
||||
@@ -47,6 +75,10 @@ export default function DownloadButton({
|
||||
return executables?.find((e) => e.id.toLowerCase() === id.toLowerCase());
|
||||
}
|
||||
|
||||
const detectedPlatform = getSystemType();
|
||||
const platformExecutable = detectedPlatform ? getExecutable(detectedPlatform) : null;
|
||||
const canAutoDownload = platformExecutable != null;
|
||||
|
||||
async function handleDownload(id: string) {
|
||||
const executable = getExecutable(id);
|
||||
if (executable == null) {
|
||||
@@ -59,16 +91,8 @@ export default function DownloadButton({
|
||||
}
|
||||
|
||||
function handleDownloadAutomatic() {
|
||||
const systemType = getSystemType();
|
||||
|
||||
// If the system type is unknown/unavailable, open the menu for manual selection
|
||||
if (systemType == null || getExecutable(systemType) == null) {
|
||||
menuRef.current?.click();
|
||||
}
|
||||
|
||||
// Otherwise, download the executable automatically
|
||||
else {
|
||||
handleDownload(systemType);
|
||||
if (canAutoDownload && detectedPlatform) {
|
||||
handleDownload(detectedPlatform);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -83,14 +107,17 @@ export default function DownloadButton({
|
||||
)}
|
||||
>
|
||||
<Button
|
||||
onClick={handleDownloadAutomatic}
|
||||
onClick={canAutoDownload ? handleDownloadAutomatic : undefined}
|
||||
suppressHydrationWarning
|
||||
disabled={disabled}
|
||||
disabled={disabled || !canAutoDownload}
|
||||
className={cn("pl-3 font-semibold pr-2.5", {
|
||||
"hover:bg-white/5": !disabled,
|
||||
"hover:bg-white/5 cursor-pointer": !disabled && canAutoDownload,
|
||||
"cursor-default": !canAutoDownload,
|
||||
})}
|
||||
>
|
||||
Download
|
||||
{canAutoDownload && detectedPlatform
|
||||
? `Download for ${getPlatformDisplayName(detectedPlatform)}`
|
||||
: "Download"}
|
||||
</Button>
|
||||
<Menu>
|
||||
<MenuButton
|
||||
@@ -115,8 +142,8 @@ export default function DownloadButton({
|
||||
onClick={() => handleDownload(executable.id)}
|
||||
>
|
||||
<div className="flex items-center gap-1.5">
|
||||
<ArrowDownTrayIcon className="size-4 fill-white/40" />
|
||||
{executable.id}
|
||||
{getPlatformIcon(executable.id, "size-4 fill-white/40")}
|
||||
{getPlatformDisplayName(executable.id)}
|
||||
</div>
|
||||
<div className="text-xs text-zinc-500">
|
||||
{(executable.size / 1024 / 1024).toFixed(1)} MiB
|
||||
|
||||
Reference in New Issue
Block a user