diff --git a/src/renderer/src/App.tsx b/src/renderer/src/App.tsx index 43b9f14..05c7214 100644 --- a/src/renderer/src/App.tsx +++ b/src/renderer/src/App.tsx @@ -1,5 +1,5 @@ import { useCallback, useState } from 'react' -import { Anchor, FolderOpen, Plus, Settings, Sparkles, TerminalSquare } from 'lucide-react' +import { Anchor, Boxes, FolderOpen, Plus, Settings, Sparkles, TerminalSquare } from 'lucide-react' import { ProjectDetail } from './components/projects/ProjectDetail' import { ProjectList } from './components/projects/ProjectList' import { TerminalPanel } from './components/terminal/TerminalPanel' @@ -7,6 +7,7 @@ import { StatusBar } from './components/layout/StatusBar' import { Toaster } from './components/ui/Toaster' import { CreateProjectModal } from './components/create/CreateProjectModal' import { SettingsModal } from './components/settings/SettingsModal' +import { GlobalModuleManager } from './components/modules/GlobalModuleManager' import { useAppStore } from './stores/appStore' import { useTerminalEvents } from './hooks/useTerminalEvents' import { useAppliedTheme } from './hooks/useAppliedTheme' @@ -17,6 +18,7 @@ function App(): React.JSX.Element { const selectedProjectName = useAppStore((s) => s.selectedProjectName) const [isCreateOpen, setIsCreateOpen] = useState(false) const [isSettingsOpen, setIsSettingsOpen] = useState(false) + const [isModulesOpen, setIsModulesOpen] = useState(false) useTerminalEvents() useAppliedTheme() useKeyboardShortcuts({ @@ -64,6 +66,9 @@ function App(): React.JSX.Element {
+
+ +
{selectedProjectName ? ( @@ -126,6 +131,7 @@ function App(): React.JSX.Element { {isCreateOpen && setIsCreateOpen(false)} />} {isSettingsOpen && setIsSettingsOpen(false)} />} + {isModulesOpen && setIsModulesOpen(false)} />} ) } diff --git a/src/renderer/src/components/create/CreateProjectModal.tsx b/src/renderer/src/components/create/CreateProjectModal.tsx index ded7ffb..319b000 100644 --- a/src/renderer/src/components/create/CreateProjectModal.tsx +++ b/src/renderer/src/components/create/CreateProjectModal.tsx @@ -12,7 +12,7 @@ import { } from 'lucide-react' import { useCreateProject } from '../../hooks/useCreateProject' import { useAppStore } from '../../stores/appStore' -import { useAvailableModules, useInstallAvailableModule, useInstallModulePackage, useModuleRegistry } from '../../hooks/useModules' +import { useModuleRegistry } from '../../hooks/useModules' import { GenericSetup } from './types/GenericSetup' import { ExternalModuleSetup } from './types/ExternalModuleSetup' import type { TypeSetupHandle } from './types/shared' @@ -52,9 +52,6 @@ export function CreateProjectModal({ onClose }: { onClose: () => void }): React. const selectProject = useAppStore((s) => s.selectProject) const setupRef = useRef(null) const { data: moduleRegistry = [] } = useModuleRegistry() - const installPackage = useInstallModulePackage() - const installAvailable = useInstallAvailableModule() - const { data: availableModules = [], isLoading: availableLoading } = useAvailableModules() const applicationModules = moduleRegistry.filter((module) => module.category === 'application') const selectedModule = applicationModules.find((module) => module.id === projectType) const getTypeLabel = (type: string): string => applicationModules.find((module) => module.id === type)?.name ?? 'project' @@ -264,15 +261,7 @@ export function CreateProjectModal({ onClose }: { onClose: () => void }): React. ) })} - {applicationModules.length === 0 &&
-

Available application modules

-

Choose a module to add to Aurora.

-
- {availableModules.filter((item) => item.manifest.category === 'application').map((item) =>

{item.manifest.name}

{item.manifest.description} · v{item.manifest.version}

)} - {!availableLoading && availableModules.filter((item) => item.manifest.category === 'application').length === 0 &&

No packages were found beside Aurora.

} -
- -
} + {applicationModules.length === 0 &&

No application modules installed

Close this window and use Modules at the bottom of the sidebar to install one.

} diff --git a/src/renderer/src/components/modules/GlobalModuleManager.tsx b/src/renderer/src/components/modules/GlobalModuleManager.tsx new file mode 100644 index 0000000..64617d5 --- /dev/null +++ b/src/renderer/src/components/modules/GlobalModuleManager.tsx @@ -0,0 +1,48 @@ +import { Boxes, Download, RefreshCw, Trash2, X } from 'lucide-react' +import { useAvailableModules, useInstallAvailableModule, useInstallModulePackage, useModuleRegistry, useUninstallModulePackage } from '../../hooks/useModules' + +function compareVersions(left: string, right: string): number { + const a = left.split(/[.-]/).map((part) => Number(part) || 0) + const b = right.split(/[.-]/).map((part) => Number(part) || 0) + for (let index = 0; index < Math.max(a.length, b.length); index += 1) { + if ((a[index] ?? 0) !== (b[index] ?? 0)) return (a[index] ?? 0) - (b[index] ?? 0) + } + return 0 +} + +export function GlobalModuleManager({ onClose }: { onClose: () => void }): React.JSX.Element { + const { data: available = [], isLoading } = useAvailableModules() + const { data: installed = [] } = useModuleRegistry() + const install = useInstallAvailableModule() + const uninstall = useUninstallModulePackage() + const installFromFolder = useInstallModulePackage() + const installedById = new Map(installed.map((module) => [module.id, module])) + + return
+
+
+

Modules

Install and manage Aurora application modules.

+ +
+
+ {isLoading ?

Loading available modules…

: available.length === 0 ?

No modules found

Place module packages beside Aurora or choose a local package folder.

:
+ {available.map(({ manifest, sourcePath }) => { + const current = installedById.get(manifest.id) + const updateAvailable = current ? compareVersions(manifest.version, current.version) > 0 : false + const busy = install.isPending || uninstall.isPending + return
+ +

{manifest.name}

{current ? `Installed ${current.version}` : `Available ${manifest.version}`}

{manifest.description}

+
+ {!current && } + {current && } + {current && } +
+
+ })} +
} +
+ +
+
+}