perf(search, run): load popups and Edit Configurations when first shown

Search Everywhere, Find in Files, the recent files/locations popups, File
Structure and the Run/Debug Configurations dialog were part of the initial
bundle although each only renders while open. `lazyWhen` mounts a lazy view
only while its condition holds; the idle prefetch still loads them right after
start-up, so opening one stays as fast.
Цей коміт міститься в:
l0ng-ai committed 2026-11-06 08:14:23 +08:00
1 джерело 4ceae47d1f
коміт 1ae8194613
6 files changed
+57 -16

No files matched your search

+7 -3
Переглянути файл
@@ -8,7 +8,7 @@ import { getContext, setContext } from "@/platform/context";
import { onIdeEvent, type RunConfig } from "@/platform/ipc";
import { useProject } from "@/platform/project";
import { onWorkflowSettingsChange } from "@/platform/workflowSettings";
import { showContextMenu, lazyComponent, type MenuItem } from "@/ui";
import { showContextMenu, lazyComponent, lazyWhen, type MenuItem } from "@/ui";
import {
menuGroupItems,
useDebugRunSessions,
@@ -35,7 +35,6 @@ import { runWithExecutor } from "./executors";
import { debugWithAgent, jdwpLaunch } from "./javaDebug";
import { RunDialogsOverlay } from "./dialogs";
import { registerExternalTools } from "./externalTools";
import { EditConfigsOverlay } from "./EditConfigsDialog";
import { openImport } from "./importConfigs";
import { registerGoActions } from "./goActions";
import { invalidateGoModules } from "./goModules";
@@ -275,6 +274,8 @@ function scheduleReload() {
reloadTimer = setTimeout(() => void loadConfigs(), 300);
}
const useEditConfigsOpen = () => useRun((s) => s.editorOpen);
export function activate(): () => void {
const disposers: Array<() => void> = [
registerToolWindow({
@@ -293,7 +294,10 @@ export function activate(): () => void {
registerBuiltinTypes(),
registerGoActions(),
registerOverlay({ id: "run.chooser", component: ConfigChooserOverlay }),
registerOverlay({ id: "run.editConfigs", component: EditConfigsOverlay }),
registerOverlay({
id: "run.editConfigs",
component: lazyWhen(useEditConfigsOpen, () => import("./EditConfigsDialog").then((m) => m.EditConfigsOverlay)),
}),
registerOverlay({ id: "run.dialogs", component: RunDialogsOverlay }),
registerServiceProvider(runServiceProvider),
registerRunningProcessesProvider({
+29 -11
Переглянути файл
@@ -3,7 +3,7 @@
* Recent Files / Recent Locations, Find / Replace in Files + the Find tool
* window, the Structure tool window + File Structure popup, and bookmarks.
*/
import { lazyComponent } from "@/ui";
import { lazyComponent, lazyWhen } from "@/ui";
import { activeEditor, registerEditorContribution } from "@/editor/api";
import { executeAction, registerActions } from "@/platform/actions";
import { shortcutLabel } from "@/platform/keymap";
@@ -33,15 +33,12 @@ import {
import { openLocation } from "./common/open";
import { maybeToolWindowService } from "./common/services";
import { installTracking, resetTracking } from "./common/tracking";
import { SearchEverywhereOverlay } from "./everywhere/SearchEverywhere";
import { hideSearchEverywhere, showSearchEverywhere } from "./everywhere/store";
import { FindInFilesOverlay } from "./find/FindInFiles";
import { hideSearchEverywhere, showSearchEverywhere, useSearchEverywhere } from "./everywhere/store";
import { ScopesDialogOverlay, showScopesDialog } from "./find/ScopesDialog";
import { hideFindPopup, parseFindArg, runFindPopupCommand, showFindPopup, useFindPopup } from "./find/store";
import { disposeFindWindow, openEditorResults, rerunActiveFindTab, useFindHeaderMenu } from "./find/windowStore";
import { RecentPopupsOverlay } from "./recent/RecentPopups";
import { cycleSwitcher, hideRecentPopup, showRecentPopup } from "./recent/store";
import { FileStructureOverlay, useFileStructurePopup } from "./structure/StructureView";
import { cycleSwitcher, hideRecentPopup, showRecentPopup, useRecentPopup } from "./recent/store";
import { useFileStructurePopup } from "./structure/popupStore";
import { useOutline, useStructureOptions } from "./structure/store";
import { tx } from "@/platform/i18n";
@@ -115,6 +112,11 @@ function jumpBookmark(dir: 1 | -1) {
if (next) void openLocation(next.b.path, { line: next.b.line, col: 0 });
}
const useEverywhereOpen = () => useSearchEverywhere((s) => s.open);
const useRecentOpen = () => useRecentPopup((s) => s.open !== null);
const useFindOpen = () => useFindPopup((s) => s.open);
const useFileStructureOpen = () => useFileStructurePopup((s) => s.open);
export function activate(): void | (() => void) {
const se = (tab: Parameters<typeof showSearchEverywhere>[0]) => () => {
closeAllPopups("everywhere");
@@ -125,11 +127,27 @@ export function activate(): void | (() => void) {
installTracking(),
provideFindResults(openEditorResults),
registerOverlay({ id: "search.everywhere", component: SearchEverywhereOverlay }),
registerOverlay({ id: "search.recent", component: RecentPopupsOverlay }),
registerOverlay({ id: "search.findInFiles", component: FindInFilesOverlay }),
registerOverlay({
id: "search.everywhere",
component: lazyWhen(useEverywhereOpen, () =>
import("./everywhere/SearchEverywhere").then((m) => m.SearchEverywhereOverlay),
),
}),
registerOverlay({
id: "search.recent",
component: lazyWhen(useRecentOpen, () => import("./recent/RecentPopups").then((m) => m.RecentPopupsOverlay)),
}),
registerOverlay({
id: "search.findInFiles",
component: lazyWhen(useFindOpen, () => import("./find/FindInFiles").then((m) => m.FindInFilesOverlay)),
}),
registerOverlay({ id: "search.scopes", component: ScopesDialogOverlay }),
registerOverlay({ id: "search.fileStructure", component: FileStructureOverlay }),
registerOverlay({
id: "search.fileStructure",
component: lazyWhen(useFileStructureOpen, () =>
import("./structure/StructureView").then((m) => m.FileStructureOverlay),
),
}),
registerOverlay({ id: "search.bookmarks", component: BookmarkPopupsOverlay }),
registerToolWindow({
+2 -1
Переглянути файл
@@ -319,7 +319,8 @@ function StructureToolbar() {
// ---------------------------------------------------------------------------
// ⌘F12 File Structure popup
export const useFileStructurePopup = create<{ open: boolean }>(() => ({ open: false }));
import { useFileStructurePopup } from "./popupStore";
export { useFileStructurePopup };
export function FileStructureOverlay() {
const open = useFileStructurePopup((s) => s.open);
+4
Переглянути файл
@@ -0,0 +1,4 @@
import { create } from "zustand";
/** Whether the File Structure popup is open. */
export const useFileStructurePopup = create<{ open: boolean }>(() => ({ open: false }));
+1 -1
Переглянути файл
@@ -32,7 +32,7 @@ export { fuzzyMatch, wordMatch } from "./match";
export { badgeKind } from "./symbolKind";
export { acquirePopup, isPopupOpen } from "./popupState";
export * from "./BarButton";
export { lazyComponent, prefetchLazyComponents } from "./lazy";
export { lazyComponent, lazyWhen, prefetchLazyComponents } from "./lazy";
export { T } from "./T";
export { selectableText, copyMenuFor, copyText } from "./selectableText";
export { useSelectionBoundary } from "./useSelectionBoundary";
+14
Переглянути файл
@@ -39,6 +39,20 @@ export function lazyComponent<P extends object>(load: () => Promise<ComponentTyp
return LazyComponent;
}
/**
* A lazy component mounted only while `useShown()` holds (a dialog's `open`), so an
* always-registered overlay doesn't load its code at start-up.
*/
export function lazyWhen<P extends object>(
useShown: () => boolean,
load: () => Promise<ComponentType<P>>,
): ComponentType<P> {
const Lazy = lazyComponent(load);
return function LazyWhen(props: P) {
return useShown() ? <Lazy {...props} /> : null;
};
}
/**
* Loads every lazy component's code one at a time while the app is idle, so a
* view opened later shows at once. Call after start-up.