installed plugins

Summary: Checking `~/.flipper/thirdparty` for already installed plugins and displaying them on top of the table

Reviewed By: jknoxville

Differential Revision: D17394821

fbshipit-source-id: 65f392c8beaf72d9effcae9f47a60bcbb9194025
This commit is contained in:
Daniel Büchele
2019-09-17 06:19:30 -07:00
committed by Facebook Github Bot
parent f3326f8874
commit 97b814d70e

View File

@@ -133,15 +133,20 @@ const TableButton = styled(Button)({
marginTop: 2, marginTop: 2,
}); });
const Spinner = styled(LoadingIndicator)({
marginTop: 6,
});
function InstallButton(props: { function InstallButton(props: {
name: string; name: string;
version: string; version: string;
onInstall: () => void; onInstall: () => void;
installed: boolean;
}) { }) {
type InstallAction = 'Install' | 'Downloading' | 'Remove'; type InstallAction = 'Install' | 'Waiting' | 'Remove';
const onInstall = useCallback(async () => { const onInstall = useCallback(async () => {
setAction('Downloading'); setAction('Waiting');
const filename = `${props.name}-${props.version}.tgz`; const filename = `${props.name}-${props.version}.tgz`;
await download({ await download({
url: `https://registry.npmjs.org/${props.name}/-/${filename}`, url: `https://registry.npmjs.org/${props.name}/-/${filename}`,
@@ -156,14 +161,18 @@ function InstallButton(props: {
}, [props.name, props.version]); }, [props.name, props.version]);
const onRemove = useCallback(async () => { const onRemove = useCallback(async () => {
fs.remove(path.join(PLUGIN_DIR, props.name)); setAction('Waiting');
await fs.remove(path.join(PLUGIN_DIR, props.name));
props.onInstall();
setAction('Install'); setAction('Install');
}, [props.name]); }, [props.name]);
const [action, setAction] = useState<InstallAction>('Install'); const [action, setAction] = useState<InstallAction>(
props.installed ? 'Remove' : 'Install',
);
if (action === 'Downloading') { if (action === 'Waiting') {
return <LoadingIndicator size={16} />; return <Spinner size={16} />;
} }
return ( return (
<TableButton <TableButton
@@ -185,7 +194,16 @@ function useNPMSearch(
return client.initIndex('npm-search'); return client.initIndex('npm-search');
}, []); }, []);
const [installedPlugins, setInstalledPlugins] = useState(
new Map<string, PluginDefinition>(),
);
useEffect(() => {
getInstalledPlugns().then(setInstalledPlugins);
}, []);
const onInstall = useCallback(async () => { const onInstall = useCallback(async () => {
setInstalledPlugins(await getInstalledPlugns());
setRestartRequired(true); setRestartRequired(true);
}, []); }, []);
@@ -215,13 +233,14 @@ function useNPMSearch(
name={h.name} name={h.name}
version={h.version} version={h.version}
onInstall={onInstall} onInstall={onInstall}
installed={installedPlugins.has(h.name)}
/> />
), ),
align: 'center' as 'center', align: 'center' as 'center',
}, },
}, },
}), }),
[], [installedPlugins],
); );
const [searchResults, setSearchResults] = useState<PluginDefinition[]>([]); const [searchResults, setSearchResults] = useState<PluginDefinition[]>([]);
@@ -234,10 +253,36 @@ function useNPMSearch(
hitsPerPage: 20, hitsPerPage: 20,
}); });
setSearchResults(hits); setSearchResults(hits.filter(hit => !installedPlugins.has(hit.name)));
setQuery(query); setQuery(query);
})(); })();
}, [query]); }, [query, installedPlugins]);
return List(searchResults.map(createRow)); const results = Array.from(installedPlugins.values()).concat(searchResults);
return List(results.map(createRow));
}
async function getInstalledPlugns() {
const dirs = await fs.readdir(PLUGIN_DIR);
const plugins = await Promise.all<[string, PluginDefinition]>(
dirs.map(
name =>
new Promise(async (resolve, reject) => {
if (!(await fs.lstat(path.join(PLUGIN_DIR, name))).isDirectory()) {
return resolve(undefined);
}
const packageJSON = await fs.readFile(
path.join(PLUGIN_DIR, name, 'package.json'),
);
try {
resolve([name, JSON.parse(packageJSON.toString())]);
} catch (e) {
reject(e);
}
}),
),
);
return new Map(plugins.filter(Boolean));
} }