2024-03-17 23:49:28 +07:00

170 lines
5.0 KiB
JavaScript

import React, { useState, useEffect } from 'react'
import axios from 'axios'
import { FaWindows, FaApple, FaLinux } from 'react-icons/fa'
import { twMerge } from 'tailwind-merge'
import { DownloadIcon } from 'lucide-react'
const systemsTemplate = [
{
name: 'Mac M1, M2, M3',
label: 'Apple Silicon',
logo: FaApple,
fileFormat: '{appname}-mac-arm64-{tag}.dmg',
},
{
name: 'Mac (Intel)',
label: 'Apple Intel',
logo: FaApple,
fileFormat: '{appname}-mac-x64-{tag}.dmg',
},
{
name: 'Windows',
label: 'Standard (64-bit)',
logo: FaWindows,
fileFormat: '{appname}-win-x64-{tag}.exe',
},
{
name: 'Linux (AppImage)',
label: 'AppImage',
logo: FaLinux,
fileFormat: '{appname}-linux-x86_64-{tag}.AppImage',
},
{
name: 'Linux (deb)',
label: 'Deb',
logo: FaLinux,
fileFormat: '{appname}-linux-amd64-{tag}.deb',
},
]
const groupTemnplate = [
{ label: 'MacOS', name: 'mac', logo: FaApple },
{ label: 'Windows', name: 'windows', logo: FaWindows },
{ label: 'Linux', name: 'linux', logo: FaLinux },
]
export default function DownloadApp() {
const [systems, setSystems] = useState(systemsTemplate)
const getLatestReleaseInfo = async (repoOwner, repoName) => {
const url = `https://api.github.com/repos/${repoOwner}/${repoName}/releases/latest`
try {
const response = await axios.get(url)
return response.data
} catch (error) {
console.error(error)
return null
}
}
const extractAppName = (fileName) => {
// Extract appname using a regex that matches the provided file formats
const regex = /^(.*?)-(?:mac|win|linux)-(?:arm64|x64|amd64|x86_64)-.*$/
const match = fileName.match(regex)
return match ? match[1] : null
}
useEffect(() => {
const updateDownloadLinks = async () => {
try {
const releaseInfo = await getLatestReleaseInfo('janhq', 'jan')
// Extract appname from the first asset name
const firstAssetName = releaseInfo.assets[0].name
const appname = extractAppName(firstAssetName)
if (!appname) {
console.error(
'Failed to extract appname from file name:',
firstAssetName
)
return
}
// Remove 'v' at the start of the tag_name
const tag = releaseInfo.tag_name.startsWith('v')
? releaseInfo.tag_name.substring(1)
: releaseInfo.tag_name
const updatedSystems = systems.map((system) => {
const downloadUrl = system.fileFormat
.replace('{appname}', appname)
.replace('{tag}', tag)
return {
...system,
href: `https://github.com/janhq/jan/releases/download/${releaseInfo.tag_name}/${downloadUrl}`,
}
})
setSystems(updatedSystems)
} catch (error) {
console.error('Failed to update download links:', error)
}
}
updateDownloadLinks()
}, [])
const renderDownloadLink = (group) => {
return (
<>
{systems
.filter((x) => x.name.toLowerCase().includes(group))
.map((system, i) => (
<div
key={i}
className="border-b border-[#F0F0F0] dark:border-gray-800 last:border-none pb-2 pt-2"
>
<a
href={system.href || ''}
className={twMerge(
'btn-shadow inline-flex text-lg my-2 font-semibold cursor-pointer justify-center items-center space-x-2] text-blue-500 hover:text-blue-500 gap-2',
system.comingSoon && 'pointer-events-none'
)}
>
<span className="text-sm">{system.label}</span>
<DownloadIcon size={16} />
</a>
</div>
))}
</>
)
}
return (
<div>
<div className="flex flex-col items-center justify-center gap-4 mb-4">
<h6 className="text-2xl font-medium">Detailed platforms</h6>
<p className="leading-relaxed text-black/60 dark:text-white/60">
Jan is in the process of being built. Expect bugs!
</p>
</div>
<div className="w-full lg:w-3/5 mx-auto px-4">
<div className="grid grid-cols-1 lg:grid-cols-3 py-10 gap-8">
{groupTemnplate.map((item, i) => {
return (
<div
className="border border-[#F0F0F0] dark:border-gray-800 rounded-xl text-center"
key={i}
>
<div className="text-center">
<div className="flex gap-2 p-4 border-b border-[#F0F0F0] dark:border-gray-800 items-center justify-center">
<div className="text-2xl">
<item.logo />
</div>
<h6>{item.label}</h6>
</div>
<div className="mx-auto text-center py-2">
{renderDownloadLink(item.name)}
</div>
</div>
</div>
)
})}
</div>
</div>
</div>
)
}