import { useMutation, useQuery } from '@tanstack/react-query'; import { openUrl } from '@tauri-apps/plugin-opener'; import type { Plugin } from '@yaakapp-internal/models'; import { pluginsAtom } from '@yaakapp-internal/models'; import type { PluginVersion } from '@yaakapp-internal/plugins'; import { checkPluginUpdates, installPlugin, searchPlugins, uninstallPlugin, } from '@yaakapp-internal/plugins'; import type { PluginUpdatesResponse } from '@yaakapp-internal/plugins/bindings/gen_api'; import { useAtomValue } from 'jotai'; import React, { useState } from 'react'; import { useDebouncedValue } from '../../hooks/useDebouncedValue'; import { useInstallPlugin } from '../../hooks/useInstallPlugin'; import { usePluginInfo } from '../../hooks/usePluginInfo'; import { useRefreshPlugins } from '../../hooks/usePlugins'; import { showConfirmDelete } from '../../lib/confirm'; import { minPromiseMillis } from '../../lib/minPromiseMillis'; import { Button } from '../core/Button'; import { CountBadge } from '../core/CountBadge'; import { IconButton } from '../core/IconButton'; import { InlineCode } from '../core/InlineCode'; import { Link } from '../core/Link'; import { LoadingIcon } from '../core/LoadingIcon'; import { PlainInput } from '../core/PlainInput'; import { HStack } from '../core/Stacks'; import { Table, TableBody, TableCell, TableHead, TableHeaderCell, TableRow } from '../core/Table'; import { TabContent, Tabs } from '../core/Tabs/Tabs'; import { EmptyStateText } from '../EmptyStateText'; import { SelectFile } from '../SelectFile'; export function SettingsPlugins() { const [directory, setDirectory] = React.useState(null); const plugins = useAtomValue(pluginsAtom); const createPlugin = useInstallPlugin(); const refreshPlugins = useRefreshPlugins(); const [tab, setTab] = useState(); return (
, }, ]} >
setDirectory(filePath)} filePath={directory} /> {directory && ( )} refreshPlugins.mutate()} /> openUrl('https://feedback.yaak.app/help/articles/6911763-quick-start') } />
); } function PluginTableRow({ plugin, updates, }: { plugin: Plugin; updates: PluginUpdatesResponse | null; }) { const pluginInfo = usePluginInfo(plugin.id); const latestVersion = updates?.plugins.find((u) => u.name === pluginInfo.data?.name)?.version; const installPluginMutation = useMutation({ mutationKey: ['install_plugin', plugin.id], mutationFn: (name: string) => installPlugin(name, null), }); const displayName = pluginInfo.data?.displayName ?? 'Unknown'; const uninstallPluginMutation = usePromptUninstall(plugin.id, displayName); if (pluginInfo.isPending) { return null; } return ( {plugin.url ? ( {displayName} ) : ( displayName )} {pluginInfo.data?.version ?? 'n/a'} {pluginInfo.data && latestVersion != null && ( )} ); } function PluginSearch() { const [query, setQuery] = useState(''); const debouncedQuery = useDebouncedValue(query); const results = useQuery({ queryKey: ['plugins', debouncedQuery], queryFn: () => searchPlugins(query), }); return (
{results.data == null ? ( ) : (results.data.plugins ?? []).length === 0 ? ( No plugins found ) : ( Name Version {results.data.plugins.map((plugin) => ( {plugin.displayName} {plugin.version} ))}
)}
); } function InstallPluginButton({ pluginVersion }: { pluginVersion: PluginVersion }) { const plugins = useAtomValue(pluginsAtom); const installed = plugins?.some((p) => p.id === pluginVersion.id); const uninstallPluginMutation = usePromptUninstall(pluginVersion.id, pluginVersion.displayName); const installPluginMutation = useMutation({ mutationKey: ['install_plugin', pluginVersion.id], mutationFn: (pv: PluginVersion) => installPlugin(pv.name, null), }); return ( ); } function InstalledPlugins() { const plugins = useAtomValue(pluginsAtom); const updates = useQuery({ queryKey: ['plugin_updates'], queryFn: () => checkPluginUpdates(), }); return plugins.length === 0 ? (
Plugins extend the functionality of Yaak.
Add your first plugin to get started.
) : ( Name Version {plugins.map((p) => { return ; })}
); } function usePromptUninstall(pluginId: string, name: string) { return useMutation({ mutationKey: ['uninstall_plugin', pluginId], mutationFn: async () => { const confirmed = await showConfirmDelete({ id: 'uninstall-plugin-' + pluginId, title: 'Uninstall Plugin', confirmText: 'Uninstall', description: ( <> Permanently uninstall {name}? ), }); if (confirmed) { await minPromiseMillis(uninstallPlugin(pluginId), 700); } }, }); }