import * as React from 'react' import { Button } from './button' import { cn } from '@/lib/utils' import { FaApple, FaWindows, FaLinux } from 'react-icons/fa' import { formatFileSize } from '@/utils/format' interface DownloadOption { id: string name: string icon: React.ReactNode size: string href: string isActive?: boolean } const downloadOptionsTemplate: DownloadOption[] = [ { id: 'mac', name: 'Download for Mac', icon: , size: '', href: '#', isActive: true, }, { id: 'windows', name: 'Download for Windows', icon: , size: '', href: '#', }, { id: 'linux-appimage', name: 'Download for Linux (AppImage)', icon: , size: '', href: '#', }, { id: 'linux-deb', name: 'Download for Linux (Deb)', icon: , size: '', href: '#', }, ] const fileFormatMap: { [key: string]: string } = { 'mac': 'Jan_{tag}_universal.dmg', 'windows': 'Jan_{tag}_x64-setup.exe', 'linux-appimage': 'Jan_{tag}_amd64.AppImage', 'linux-deb': 'Jan_{tag}_amd64.deb', } interface DropdownButtonProps { size?: 'default' | 'sm' | 'lg' | 'xl' | 'icon' | 'xxl' className?: string classNameButton?: string lastRelease?: any } export function DropdownButton({ size = 'xl', className, classNameButton, lastRelease, }: DropdownButtonProps) { const [isOpen, setIsOpen] = React.useState(false) const [downloadOptions, setDownloadOptions] = React.useState( downloadOptionsTemplate ) const [currentOption, setCurrentOption] = React.useState( downloadOptions.find((opt) => opt.isActive) || downloadOptions[0] ) const dropdownRef = React.useRef(null) const toggleDropdown = () => setIsOpen(!isOpen) const selectOption = (option: DownloadOption) => { setCurrentOption(option) setIsOpen(false) } const changeDefaultSystem = React.useCallback((systems: DownloadOption[]) => { const userAgent = navigator.userAgent if (userAgent.includes('Windows')) { // windows user const windowsOption = systems.find((opt) => opt.id === 'windows') if (windowsOption) setCurrentOption(windowsOption) } else if (userAgent.includes('Linux')) { // linux user - prefer deb package const linuxOption = systems.find((opt) => opt.id === 'linux-deb') if (linuxOption) setCurrentOption(linuxOption) } else if (userAgent.includes('Mac OS')) { // mac user - always use universal build const macOption = systems.find((opt) => opt.id === 'mac') if (macOption) setCurrentOption(macOption) } else { // fallback to windows const windowsOption = systems.find((opt) => opt.id === 'windows') if (windowsOption) setCurrentOption(windowsOption) } }, []) React.useEffect(() => { if (lastRelease) { try { const tag = lastRelease.tag_name.startsWith('v') ? lastRelease.tag_name.substring(1) : lastRelease.tag_name const updatedOptions = downloadOptionsTemplate.map((option) => { const fileFormat = fileFormatMap[option.id] const fileName = fileFormat.replace('{tag}', tag) // Find the corresponding asset to get the file size const asset = lastRelease.assets.find( (asset: any) => asset.name === fileName ) return { ...option, href: `https://github.com/janhq/jan/releases/download/${lastRelease.tag_name}/${fileName}`, size: asset ? formatFileSize(asset.size) : 'N/A', } }) setDownloadOptions(updatedOptions) changeDefaultSystem(updatedOptions) } catch (error) { console.error('Failed to update download links:', error) } } }, [lastRelease, changeDefaultSystem]) React.useEffect(() => { const handleEscapeKey = (event: KeyboardEvent) => { if (event.key === 'Escape' && isOpen) { setIsOpen(false) } } const handleClickOutside = (event: MouseEvent) => { if ( dropdownRef.current && !dropdownRef.current.contains(event.target as Node) ) { setIsOpen(false) } } if (isOpen) { document.addEventListener('keydown', handleEscapeKey) document.addEventListener('mousedown', handleClickOutside) } return () => { document.removeEventListener('keydown', handleEscapeKey) document.removeEventListener('mousedown', handleClickOutside) } }, [isOpen]) return ( {/* Main Button */} {currentOption.icon} {currentOption.name} {/* Dropdown Toggle */} {/* Dropdown Menu */} {isOpen && ( {downloadOptions.map((option) => ( { selectOption(option) setIsOpen(false) }} > {option.icon} {option.name} {option.size} ))} )} ) }