import { invoke } from "@tauri-apps/api/core"; import { Download, Search, Github, Globe, CheckCircle } from "lucide-react"; import React, { useState, useEffect } from "react"; interface StoreApp { name: string; description: string; authors?: { name: string }[]; links?: { type: string; url: string }[]; icons?: string[]; github_url?: string; stargazers_count?: number; categories?: string[]; } interface StorefrontProps { installedAppNames?: string[]; onRefreshLibrary?: () => void; } const Storefront: React.FC = ({ installedAppNames = [], onRefreshLibrary }) => { const [apps, setApps] = useState([]); const [loading, setLoading] = useState(true); const [error, setError] = useState(null); const [searchTerm, setSearchTerm] = useState(""); const [source, setSource] = useState<"appimagehub" | "github">("appimagehub"); const [downloadingName, setDownloadingName] = useState(null); useEffect(() => { fetchData(); }, [source]); const fetchData = async () => { try { setLoading(true); setError(null); const controller = new AbortController(); const timeout = setTimeout(() => controller.abort(), 15000); if (source === "appimagehub") { const response = await fetch("https://appimage.github.io/feed.json", { signal: controller.signal, }); if (!response.ok) throw new Error("Failed to fetch AppImageHub data"); const data = await response.json(); setApps(data.items || []); } else { const response = await fetch( "https://api.github.com/search/repositories?q=topic:appimage&sort=stars&order=desc&per_page=100", { signal: controller.signal } ); if (!response.ok) throw new Error("Failed to fetch GitHub data"); const data = await response.json(); const githubApps = data.items.map((item: any) => ({ name: item.name, description: item.description, authors: [{ name: item.owner.login }], links: [{ type: "GitHub", url: item.html_url }], github_url: item.html_url, stargazers_count: item.stargazers_count, icons: [item.owner.avatar_url], })); setApps(githubApps); } clearTimeout(timeout); } catch (err: any) { console.error(err); if (err?.name === "AbortError") { setError("Request timed out. Check your internet connection."); } else { setError(String(err)); } } finally { setLoading(false); } }; const isInstalled = (appName: string) => { const lowerName = appName.toLowerCase().trim(); return installedAppNames.some( (n) => n.toLowerCase().trim() === lowerName || lowerName.includes(n.toLowerCase().trim()) ); }; const filteredApps = apps.filter( (app) => app.name.toLowerCase().includes(searchTerm.toLowerCase()) || (app.description && app.description.toLowerCase().includes(searchTerm.toLowerCase())) ); return (

Discover AppImages

{source === "appimagehub" ? "Browsing AppImageHub Official Catalog" : "Browsing Popular GitHub AppImage Projects"}

setSearchTerm(e.target.value)} style={{ width: "100%", padding: "10px 14px 10px 40px", background: "var(--bg-input)", border: "1px solid var(--border-color)", borderRadius: "8px", color: "var(--text-primary)", fontSize: "14px", outline: "none", }} />
{loading && (
Fetching {source === "github" ? "GitHub projects" : "Hub catalog"}...
)} {error && (
{error}
)}
{filteredApps.map((app, idx) => { const githubLink = app.links?.find( (l) => l.type.toLowerCase() === "github" || l.type.toLowerCase() === "homepage" ); const downloadLink = app.links?.find((l) => l.type.toLowerCase() === "download") || githubLink; const installed = isInstalled(app.name); const isBusy = downloadingName === app.name; return (
{app.icons && app.icons.length > 0 ? ( {app.name} ) : (
)}
{app.name}
{source === "github" && } {app.authors?.[0]?.name || "Community"} {app.stargazers_count !== undefined && ( ★ {app.stargazers_count} )}
{app.description || "No description available for this project."}
{installed ? (
Installed
) : ( )} {app.github_url && ( )}
); })}
{!loading && filteredApps.length === 0 && (
No applications found matching your search.
)}
); }; export default Storefront;