import * as React from 'react'; import useAsyncEffect from '@joplin/lib/hooks/useAsyncEffect'; import { _ } from '@joplin/lib/locale'; import { PluginManifest } from '@joplin/lib/services/plugins/utils/types'; import { useCallback, useMemo, useState } from 'react'; import { FlatList, View } from 'react-native'; import { Searchbar } from 'react-native-paper'; import PluginBox, { InstallState } from './PluginBox'; import PluginService, { PluginSettings, SerializedPluginSettings } from '@joplin/lib/services/plugins/PluginService'; import useInstallHandler from '@joplin/lib/components/shared/config/plugins/useOnInstallHandler'; import { OnPluginSettingChangeEvent, PluginItem } from '@joplin/lib/components/shared/config/plugins/types'; import RepositoryApi from '@joplin/lib/services/plugins/RepositoryApi'; import openWebsiteForPlugin from './utils/openWebsiteForPlugin'; interface Props { themeId: number; pluginSettings: SerializedPluginSettings; repoApiInitialized: boolean; onUpdatePluginStates: (states: PluginSettings)=> void; repoApi: RepositoryApi; } interface SearchResultRecord { id: string; item: PluginItem; installState: InstallState; } const PluginSearch: React.FC = props => { const [searchQuery, setSearchQuery] = useState(''); const [searchResultManifests, setSearchResultManifests] = useState([]); useAsyncEffect(async event => { if (!searchQuery || !props.repoApiInitialized) { setSearchResultManifests([]); } else { const results = await props.repoApi.search(searchQuery); if (event.cancelled) return; setSearchResultManifests(results); } }, [searchQuery, props.repoApi, setSearchResultManifests, props.repoApiInitialized]); const [installingPluginsIds, setInstallingPluginIds] = useState>({}); const pluginSettings = useMemo(() => { return { ...PluginService.instance().unserializePluginSettings(props.pluginSettings) }; }, [props.pluginSettings]); const searchResults: SearchResultRecord[] = useMemo(() => { return searchResultManifests.map(manifest => { const settings = pluginSettings[manifest.id]; let installState = InstallState.NotInstalled; if (settings && !settings.deleted) { installState = InstallState.Installed; } if (installingPluginsIds[manifest.id]) { installState = InstallState.Installing; } const item: PluginItem = { manifest, enabled: settings && settings.enabled, deleted: settings && !settings.deleted, devMode: false, builtIn: false, hasBeenUpdated: false, }; return { id: manifest.id, item, installState, }; }); }, [searchResultManifests, installingPluginsIds, pluginSettings]); const onPluginSettingsChange = useCallback((event: OnPluginSettingChangeEvent) => { props.onUpdatePluginStates(event.value); }, [props.onUpdatePluginStates]); const installPlugin = useInstallHandler( setInstallingPluginIds, pluginSettings, props.repoApi, onPluginSettingsChange, false, ); const renderResult = useCallback(({ item }: { item: SearchResultRecord }) => { const manifest = item.item.manifest; return ( ); }, [installPlugin, props.themeId]); return ( item.id} scrollEnabled={false} /> ); }; export default PluginSearch;