diff --git a/src/features/run/index.ts b/src/features/run/index.ts index 10ffa6113..9bb61ea57 100644 --- a/src/features/run/index.ts +++ b/src/features/run/index.ts @@ -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({ diff --git a/src/features/search/index.ts b/src/features/search/index.ts index a5cbcd4dc..725549b5a 100644 --- a/src/features/search/index.ts +++ b/src/features/search/index.ts @@ -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[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({ diff --git a/src/features/search/structure/StructureView.tsx b/src/features/search/structure/StructureView.tsx index c1b55621f..b4aa2655f 100644 --- a/src/features/search/structure/StructureView.tsx +++ b/src/features/search/structure/StructureView.tsx @@ -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); diff --git a/src/features/search/structure/popupStore.ts b/src/features/search/structure/popupStore.ts new file mode 100644 index 000000000..9030f1a72 --- /dev/null +++ b/src/features/search/structure/popupStore.ts @@ -0,0 +1,4 @@ +import { create } from "zustand"; + +/** Whether the File Structure popup is open. */ +export const useFileStructurePopup = create<{ open: boolean }>(() => ({ open: false })); diff --git a/src/ui/index.ts b/src/ui/index.ts index 5633d0a1d..c77386e7a 100644 --- a/src/ui/index.ts +++ b/src/ui/index.ts @@ -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"; diff --git a/src/ui/lazy.tsx b/src/ui/lazy.tsx index b9221e341..00aea73f4 100644 --- a/src/ui/lazy.tsx +++ b/src/ui/lazy.tsx @@ -39,6 +39,20 @@ export function lazyComponent

(load: () => Promise( + useShown: () => boolean, + load: () => Promise>, +): ComponentType

{ + const Lazy = lazyComponent(load); + return function LazyWhen(props: P) { + return useShown() ? : 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.