feat: hide installed plugins in the browse tab by default

This commit is contained in:
LukeGus committed 2026-10-11 17:10:09 -05:00
1 parent 11f4674bd2
commit 9c63d8d433
4 files changed
+53 -9

No files matched your search

+1
View File
@@ -14,6 +14,7 @@
- Every language is now fully translated, in Termix and in every plugin, and stays up to date with each release
- Languages with more than two plural forms, like Russian, Polish and Arabic, now use the right one
- The Plugins tab shows how many times each plugin was downloaded, in a Downloads column
- Plugins, Browse hides plugins you already have. Turn on Show installed to see them
### Fixed
+3
View File
@@ -2085,6 +2085,9 @@
"noneInstalled": "No plugins installed yet. Browse to add some.",
"nothingHere": "Nothing here.",
"nothingHereHint": "Try another category or search.",
"showInstalled": "Show installed",
"allInstalled": "Everything here is already installed.",
"allInstalledHint": "Turn on Show installed to see them.",
"communitySubmit": "How to submit",
"registries": {
"intro": "Registries are lists of plugins you can install. The official one is always on. You can turn on the community registry or add your own.",
+36 -9
View File
@@ -952,6 +952,12 @@ function BrowseSection({
const [category, setCategory] = useState<string | null>(null);
const [registry, setRegistry] = useState<string | null>(null);
const [sort, setSort] = useState<SortKey>("popular");
const [installedChoice, setInstalledChoice] = useStoredChoice(
"pluginsTab.browseInstalled",
["hide", "show"],
"hide",
);
const showInstalled = installedChoice === "show";
const categories = useMemo(() => categoriesOf(plugins), [plugins]);
const registries = manager.registries;
const registryFilter = registries.some((entry) => entry.id === registry)
@@ -961,6 +967,7 @@ function BrowseSection({
const rows = sortPlugins(
plugins.filter(
(p) =>
(showInstalled || !p.installed) &&
matchesQuery(p, query) &&
(category === null || p.category === category) &&
(registryFilter === null || p.registryId === registryFilter),
@@ -968,6 +975,9 @@ function BrowseSection({
sort,
);
const allInstalledHidden =
!showInstalled && plugins.length > 0 && plugins.every((p) => p.installed);
const listColumns: DataColumn<PluginEntry>[] = [
{
key: "name",
@@ -1029,6 +1039,15 @@ function BrowseSection({
placeholder={t("plugins.manager.searchPlugins")}
>
<div className="ml-auto flex items-center gap-2">
<label className="flex items-center gap-1.5">
<span className="text-xs text-muted-foreground">
{t("plugins.manager.showInstalled")}
</span>
<FakeSwitch
checked={showInstalled}
onChange={(v) => setInstalledChoice(v ? "show" : "hide")}
/>
</label>
{registries.length > 1 && (
<Select
value={registryFilter ?? "__all"}
@@ -1084,15 +1103,23 @@ function BrowseSection({
)}
{rows.length === 0 ? (
<EmptyState
icon={Puzzle}
title={t("plugins.manager.nothingHere")}
hint={
plugins.length === 0
? undefined
: t("plugins.manager.nothingHereHint")
}
/>
allInstalledHidden ? (
<EmptyState
icon={Puzzle}
title={t("plugins.manager.allInstalled")}
hint={t("plugins.manager.allInstalledHint")}
/>
) : (
<EmptyState
icon={Puzzle}
title={t("plugins.manager.nothingHere")}
hint={
plugins.length === 0
? undefined
: t("plugins.manager.nothingHereHint")
}
/>
)
) : (
<PluginCollection
plugins={rows}
+13
View File
@@ -73,6 +73,19 @@ describe("PluginsTab", () => {
expect(link.getAttribute("href")).toBe(docsUrl("communityRegistry"));
});
it("hides installed plugins in Browse until shown", async () => {
await renderTab();
fireEvent.click(screen.getByText(en.plugins.manager.tabs.browse));
expect(screen.queryByText("Demo Plugin")).toBeNull();
expect(screen.getByText(en.plugins.manager.allInstalled)).toBeTruthy();
fireEvent.click(screen.getByRole("switch"));
expect(screen.getByText("Demo Plugin")).toBeTruthy();
expect(localStorage.getItem("pluginsTab.browseInstalled")).toBe("show");
});
it("switches to a table and remembers it", async () => {
await renderTab();
expect(screen.queryByRole("table")).toBeNull();