import { useEffect, useMemo, useRef, useState } from 'react'; import { PowerIcon, RestartIcon } from '../icons.jsx'; import { nebula } from '../../lib/nebula.js'; import { IconButton } from '../ui/IconButton.jsx'; import { SearchField } from '../ui/SearchField.jsx'; import { AppItem } from './AppItem.jsx'; import './Launcher.css'; function matchesQuery(app, query) { if (!query) { return true; } const haystack = `${app.name} ${app.comment ?? ''}`.toLowerCase(); return haystack.includes(query); } export function Launcher({ open, apps, recents, projects, user, onLaunch, onOpenProject, }) { const [query, setQuery] = useState(''); const [wasOpen, setWasOpen] = useState(open); const searchRef = useRef(null); if (open !== wasOpen) { setWasOpen(open); if (!open) { setQuery(''); } } useEffect(() => { if (!open) { return undefined; } const frame = window.requestAnimationFrame(() => { searchRef.current?.focus(); }); return () => window.cancelAnimationFrame(frame); }, [open]); const filteredApps = useMemo(() => { const normalised = query.trim().toLowerCase(); return apps.filter((app) => matchesQuery(app, normalised)); }, [apps, query]); const searching = query.trim().length > 0; return (
{!searching && recents.length > 0 ? (

Recent

{recents.map((app) => ( ))}
) : null}

{searching ? 'Results' : 'Applications'}

{filteredApps.length > 0 ? (
{filteredApps.map((app) => ( ))}
) : (

No matching applications

)}
{!searching && projects.length > 0 ? (

Recent projects

{projects.map((project) => ( ))}
) : null}
); }