From 859f63454eed53ae97eb5881d5f076504848a6aa Mon Sep 17 00:00:00 2001 From: l0ng-ai <24760907+l0ng-ai@users.noreply.github.com> Date: Wed, 4 Nov 2026 21:38:59 +0800 Subject: [PATCH] fix(plugins): move the repository URL to the gear menu and drop the no-repository hint (#1282) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The Available tab always showed a "There is no online plugin repository" notice under the search field when no index was set. Release builds use the official index by default, so the notice only appeared in development builds, where the empty URL field above it already said the same thing. The URL field itself sat at the top of the list although most people never change it. - The notice is gone, and the search placeholder reads "Search plugins" because the list holds marketplace plugins as well as local ones. - With a repository configured, the empty details panel says "No plugin selected" instead of claiming there is no online repository. - The marketplace index URL is edited from the gear menu's "Plugin Repository…" dialog; leaving it empty restores the default. --- src/features/plugins/PluginsPage.module.css | 11 ---- src/features/plugins/PluginsPage.tsx | 56 +++++++------------ .../plugins/__tests__/plugins.test.tsx | 49 +++++++++++++++- src/platform/locales/text/fr.json | 5 -- src/platform/locales/text/ko.json | 5 -- src/platform/locales/text/zh.json | 10 ++-- 6 files changed, 74 insertions(+), 62 deletions(-) diff --git a/src/features/plugins/PluginsPage.module.css b/src/features/plugins/PluginsPage.module.css index a2764a19b..90b2c7398 100644 --- a/src/features/plugins/PluginsPage.module.css +++ b/src/features/plugins/PluginsPage.module.css @@ -369,17 +369,6 @@ padding: 4px 8px; } -.marketBar { - display: flex; - gap: 4px; - align-items: center; -} - -.marketBar > :first-child { - flex: 1; - min-width: 0; -} - .categorySelect { width: 100%; } diff --git a/src/features/plugins/PluginsPage.tsx b/src/features/plugins/PluginsPage.tsx index f2dac512a..7c66e6c15 100644 --- a/src/features/plugins/PluginsPage.tsx +++ b/src/features/plugins/PluginsPage.tsx @@ -16,7 +16,6 @@ import { EmptyState, Icon, IconButton, - Input, SearchField, Select, Spinner, @@ -48,6 +47,7 @@ import { } from "./store"; import { useProject } from "@/platform/project"; import { importIntellijTheme, showInstalledIntellijThemes } from "./intellijImport"; +import { promptInput } from "@/workbench/inputDialogs"; import styles from "./PluginsPage.module.css"; import { tx } from "@/platform/i18n"; @@ -537,6 +537,21 @@ interface GearActions { install: (packageFile: boolean) => void; importIntellijFile: () => void; importInstalledIntellij: () => void; + editRepository: () => void; +} + +/** Asks for the marketplace index URL; an empty one restores the default. */ +async function editMarketUrl() { + const url = await promptInput({ + title: "Plugin Repository", + label: "Marketplace index URL:", + initial: usePlugins.getState().marketUrl ?? "", + placeholder: "https://…/index.json or a folder path", + okLabel: "Save", + validate: () => null, + hint: Leave empty to use the default repository., + }); + if (url !== null) await setMarketUrl(url); } function gearMenu(plugins: readonly PluginInfo[], updates: number, actions: GearActions): MenuItem[] { @@ -550,6 +565,7 @@ function gearMenu(plugins: readonly PluginInfo[], updates: number, actions: Gear { kind: "separator" }, { label: "Install Plugin from Disk…", icon: "package", run: () => actions.install(false) }, { label: "Install Plugin from Package File…", run: () => actions.install(true) }, + { label: "Plugin Repository…", run: actions.editRepository }, ...(actions.canImport ? [ { kind: "separator" as const }, @@ -654,30 +670,6 @@ function CategoryFilter({ ); } -/** The marketplace index URL, editable in place. */ -function MarketUrlBar() { - const current = usePlugins((s) => s.marketUrl); - const [value, setValue] = useState(current ?? ""); - useEffect(() => setValue(current ?? ""), [current]); - return ( -
{ - e.preventDefault(); - void setMarketUrl(value); - }} - > - setValue(e.target.value)} - /> - - - ); -} - function MarketRow({ entry, selected, onSelect }: { entry: MarketPlugin; selected: boolean; onSelect: () => void }) { const update = isUpdate(entry); return ( @@ -832,6 +824,7 @@ export function PluginsPage() { install: (packageFile) => void installFromDisk(undefined, packageFile).then(showInstalled), importIntellijFile: () => void importIntellijTheme().then(showInstalled), importInstalledIntellij: () => showInstalledIntellijThemes(showInstalled), + editRepository: () => void editMarketUrl(), }), ); }; @@ -876,7 +869,7 @@ export function PluginsPage() { className={styles.search} value={query} onChange={setQuery} - placeholder={tab === "installed" ? "Search installed plugins" : "Search local plugins"} + placeholder={tab === "installed" ? "Search installed plugins" : "Search plugins"} aria-label="Filter plugins" /> {tab === "installed" ? ( @@ -916,20 +909,11 @@ export function PluginsPage() { ) : (