Skip to content

Commit

Permalink
Refactor the implementation and bug fixing (#1348)
Browse files Browse the repository at this point in the history
- Extract the logic about error handling out of the classpath view.
- Remove some redundent effects.
- Fix dropdown css bugs.
- Fix the bug that activeProjectIndex not currently used in handlers.
- Fix the bug when handling the library paths.
  • Loading branch information
jdneo authored Jun 3, 2024
1 parent 1acb978 commit 805a1d3
Show file tree
Hide file tree
Showing 23 changed files with 444 additions and 453 deletions.
2 changes: 0 additions & 2 deletions src/extension.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,7 @@ import { initialize as initUtils } from "./utils";
import { KEY_SHOW_WHEN_USING_JAVA } from "./utils/globalState";
import { scheduleAction } from "./utils/scheduler";
import { showWelcomeWebview, WelcomeViewSerializer } from "./welcome";
import { activateCopilotInspection } from "./copilot/inspect";
import { ProjectSettingsViewSerializer } from "./project-settings/projectSettingsView";
import { isLlmApiReady } from "./copilot/utils";

let cleanJavaWorkspaceIndicator: string;
let activatedTimestamp: number;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,90 +7,59 @@ import { Dispatch } from "@reduxjs/toolkit";
import Output from "./components/Output";
import Sources from "./components/Sources";
import Libraries from "./components/Libraries";
import Exception from "./components/Exception";
import { ClasspathViewException, ProjectInfo } from "../../../types";
import { catchException, listVmInstalls, loadClasspath, updateActiveTab } from "./classpathConfigurationViewSlice";
import { listVmInstalls, updateActiveTab } from "./classpathConfigurationViewSlice";
import JdkRuntime from "./components/JdkRuntime";
import { ClasspathRequest } from "../../vscode/utils";
import { VSCodePanelTab, VSCodePanelView, VSCodePanels, VSCodeProgressRing } from "@vscode/webview-ui-toolkit/react";
import { VSCodePanelTab, VSCodePanelView, VSCodePanels } from "@vscode/webview-ui-toolkit/react";
import { ProjectType } from "../../../../utils/webview";
import UnmanagedFolderSources from "./components/UnmanagedFolderSources";
import Hint from "./components/Hint";
import "../style.scss";
import { setProjectType } from "../../mainpage/features/commonSlice";

const ClasspathConfigurationView = (): JSX.Element => {
const activeTab: string = useSelector((state: any) => state.classpathConfig.ui.activeTab);
const activeProjectIndex: number = useSelector((state: any) => state.commonConfig.ui.activeProjectIndex);
const projects: ProjectInfo[] = useSelector((state: any) => state.commonConfig.data.projects);
const projectType: ProjectType = useSelector((state: any) => state.commonConfig.data.projectType[activeProjectIndex]);
const exception: ClasspathViewException | undefined = useSelector((state: any) => state.classpathConfig.exception);
const dispatch: Dispatch<any> = useDispatch();

const onClickTab = (tabId: string) => {
dispatch(updateActiveTab(tabId));
};

let content: JSX.Element;
if (exception) {
content = <Exception />;
} else if (projects.length === 0) {
content = <VSCodeProgressRing></VSCodeProgressRing>;
} else {
content = (
<div className="root">
<VSCodePanels activeid={activeTab} className="setting-panels">
<VSCodePanelTab id="source" onClick={() => onClickTab("source")}>Sources</VSCodePanelTab>
<VSCodePanelTab id="jdk" onClick={() => onClickTab("jdk")}>JDK Runtime</VSCodePanelTab>
<VSCodePanelTab id="libraries" onClick={() => onClickTab("libraries")}>Libraries</VSCodePanelTab>
<VSCodePanelView className="setting-panels-view">
{[ProjectType.Gradle, ProjectType.Maven].includes(projectType) && (<Sources />)}
{projectType !== ProjectType.Gradle && projectType !== ProjectType.Maven && (<UnmanagedFolderSources />)}
{projectType === ProjectType.UnmanagedFolder && (<Output />)}
</VSCodePanelView>
<VSCodePanelView className="setting-panels-view">
<JdkRuntime />
</VSCodePanelView>
<VSCodePanelView className="setting-panels-view">
<Libraries />
</VSCodePanelView>
</VSCodePanels>
<Hint />
</div>
);
}

const onMessage = (event: any) => {
const { data } = event;
if (data.command === "classpath.onDidListVmInstalls") {
dispatch(listVmInstalls(data.vmInstalls))
} else if (data.command === "classpath.onDidLoadProjectClasspath") {
dispatch(setProjectType({
projectType: data.projectType
}));
dispatch(loadClasspath({
activeProjectIndex,
...data
}));
} else if (data.command === "classpath.onException") {
dispatch(catchException(data.exception));
}
};

useEffect(() => {
window.addEventListener("message", onMessage);
if (projects.length == 0) {
// this makes sure the initialization only happens when the
// redux store is empty. When switching between tabs, the
// state will be preserved.
ClasspathRequest.onWillListProjects();
}
return () => {
window.removeEventListener("message", onMessage);
}
}, []);

return content;
return (
<div className="root">
<VSCodePanels activeid={activeTab} className="setting-panels">
<VSCodePanelTab id="source" onClick={() => onClickTab("source")}>Sources</VSCodePanelTab>
<VSCodePanelTab id="jdk" onClick={() => onClickTab("jdk")}>JDK Runtime</VSCodePanelTab>
<VSCodePanelTab id="libraries" onClick={() => onClickTab("libraries")}>Libraries</VSCodePanelTab>
<VSCodePanelView className="setting-panels-view">
{[ProjectType.Gradle, ProjectType.Maven].includes(projectType) && (<Sources />)}
{projectType !== ProjectType.Gradle && projectType !== ProjectType.Maven && (<UnmanagedFolderSources />)}
{projectType === ProjectType.UnmanagedFolder && (<Output />)}
</VSCodePanelView>
<VSCodePanelView className="setting-panels-view">
<JdkRuntime />
</VSCodePanelView>
<VSCodePanelView className="setting-panels-view">
<Libraries />
</VSCodePanelView>
</VSCodePanels>
<Hint />
</div>
);
};

export default ClasspathConfigurationView;
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,6 @@ export const classpathConfigurationViewSlice = createSlice({
output: [] as string[],
libraries: [] as ClasspathEntry[][],
},
loadingState: false, // TODO: move to common?
exception: undefined,
},
reducers: {
updateActiveTab: (state, action) => {
Expand Down Expand Up @@ -107,12 +105,6 @@ export const classpathConfigurationViewSlice = createSlice({
newLibs = _.uniq(newLibs);
state.data.libraries[activeProjectIndex] = _.uniqBy(newLibs, "path");
},
catchException: (state, action) => {
state.exception = action.payload;
},
updateLoadingState: (state, action) => {
state.loadingState = action.payload;
},
},
});

Expand All @@ -130,8 +122,6 @@ export const {
setJdks,
removeReferencedLibrary,
addLibraries,
catchException,
updateLoadingState,
flushClasspathToEffective,
} = classpathConfigurationViewSlice.actions;

Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT license.

import React, { Dispatch, useEffect, useState } from "react";
import React, { Dispatch, useEffect, useRef, useState } from "react";
import { ClasspathRequest, CommonRequest } from "../../../vscode/utils";
import { VSCodeDivider, VSCodeDropdown, VSCodeOption, } from "@vscode/webview-ui-toolkit/react";
import { useDispatch, useSelector } from "react-redux";
Expand All @@ -11,6 +11,11 @@ import { setJdks } from "../classpathConfigurationViewSlice";
const JdkRuntime = (): JSX.Element => {

const activeProjectIndex: number = useSelector((state: any) => state.commonConfig.ui.activeProjectIndex);
const activeProjectIndexRef = useRef(activeProjectIndex);
useEffect(() => {
activeProjectIndexRef.current = activeProjectIndex;
}, [activeProjectIndex]);

const vmInstalls: VmInstall[] = useSelector((state: any) => state.classpathConfig.data.vmInstalls);
const activeVmInstallPath: string = useSelector((state: any) => state.classpathConfig.data.activeVmInstallPath[activeProjectIndex]);

Expand All @@ -35,12 +40,26 @@ const JdkRuntime = (): JSX.Element => {
const {data} = event;
if (data.command === "classpath.onDidChangeJdk") {
dispatch(setJdks({
activeProjectIndex,
activeProjectIndex: activeProjectIndexRef.current,
...data
}));
}
}

useEffect(() => {
window.addEventListener("message", onDidChangeJdk);
// the dropdown list has a fixed height by default, which makes the list jitter
// when the jdk path changes. We set the max-height to initial to fix this issue.
// Note that the list box is rendered inside a shadow dom so this is the only way
// to change its style.
document.querySelector("#jdk-dropdown")?.shadowRoot
?.querySelector(".listbox")?.setAttribute("style", "max-height: initial;");
if (vmInstalls.length === 0) {
ClasspathRequest.onWillListVmInstalls();
}
return () => window.removeEventListener("message", onDidChangeJdk);
}, []);

const jdkSelections = vmInstalls.map((vmInstall) => {
return (
<VSCodeOption
Expand Down Expand Up @@ -89,20 +108,6 @@ const JdkRuntime = (): JSX.Element => {
</VSCodeOption>
);

useEffect(() => {
window.addEventListener("message", onDidChangeJdk);
// the dropdown list has a fixed height by default, which makes the list jitter
// when the jdk path changes. We set the max-height to initial to fix this issue.
// Note that the list box is rendered inside a shadow dom so this is the only way
// to change its style.
document.querySelector("#jdk-dropdown")?.shadowRoot
?.querySelector(".listbox")?.setAttribute("style", "max-height: initial;");
if (vmInstalls.length === 0) {
ClasspathRequest.onWillListVmInstalls();
}
return () => window.removeEventListener("message", onDidChangeJdk);
}, []);

return (
<div className="setting-section">
<div className="flex-center mt-2">
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
// Licensed under the MIT license.

import { Dispatch } from "@reduxjs/toolkit";
import React, { useEffect, useState } from "react";
import React, { useEffect, useRef, useState } from "react";
import { useSelector, useDispatch } from "react-redux";
import { removeReferencedLibrary, addLibraries } from "../classpathConfigurationViewSlice";
import { ClasspathRequest } from "../../../vscode/utils";
Expand All @@ -13,6 +13,11 @@ const Libraries = (): JSX.Element => {

const [hoveredRow, setHoveredRow] = useState<string | null>(null);
const activeProjectIndex: number = useSelector((state: any) => state.commonConfig.ui.activeProjectIndex);
const activeProjectIndexRef = useRef(activeProjectIndex);
useEffect(() => {
activeProjectIndexRef.current = activeProjectIndex;
}, [activeProjectIndex]);

const libraries: ClasspathEntry[] = useSelector((state: any) => state.classpathConfig.data.libraries[activeProjectIndex]);
const dispatch: Dispatch<any> = useDispatch();

Expand All @@ -31,12 +36,19 @@ const Libraries = (): JSX.Element => {
const {data} = event;
if (data.command === "classpath.onDidAddLibraries") {
dispatch(addLibraries({
activeProjectIndex,
activeProjectIndex: activeProjectIndexRef.current,
libraries:data.jars
}));
}));
}
};

useEffect(() => {
window.addEventListener("message", onDidAddLibraries);
return () => {
window.removeEventListener("message", onDidAddLibraries);
}
}, []);

const resolveLibPath = (entry: ClasspathEntry): string => {
if (entry.kind === ClasspathEntryKind.Project) {
return resolveProjectPath(entry);
Expand Down Expand Up @@ -68,13 +80,6 @@ const Libraries = (): JSX.Element => {
return pathComponents[pathComponents.length - 1];
}

useEffect(() => {
window.addEventListener("message", onDidAddLibraries);
return () => {
window.removeEventListener("message", onDidAddLibraries);
}
}, []);

let librariesSections: JSX.Element | JSX.Element[];
if (libraries.length === 0) {
librariesSections = (
Expand Down
Loading

0 comments on commit 805a1d3

Please sign in to comment.