From 8b0d4e0361c3af3179036ed414d2da1e3bc7d68c Mon Sep 17 00:00:00 2001 From: Filip Andrzej Kaminski Date: Tue, 26 Mar 2024 19:33:14 +0100 Subject: [PATCH] init --- .../vscode-extension/src/common/Project.ts | 2 +- .../src/common/WorkspaceConfig.ts | 94 +++++++++++++++++++ .../src/panels/SidepanelViewProvider.ts | 2 +- .../src/panels/WebviewController.ts | 8 +- .../vscode-extension/src/project/project.ts | 6 ++ .../webview/components/SettingsDropdown.tsx | 26 ++++- .../vscode-extension/src/webview/index.jsx | 21 +++-- .../providers/WorkspaceConfigProvider.tsx | 41 ++++++++ 8 files changed, 185 insertions(+), 15 deletions(-) create mode 100644 packages/vscode-extension/src/common/WorkspaceConfig.ts create mode 100644 packages/vscode-extension/src/webview/providers/WorkspaceConfigProvider.tsx diff --git a/packages/vscode-extension/src/common/Project.ts b/packages/vscode-extension/src/common/Project.ts index 856c300f8..37bc12aa9 100644 --- a/packages/vscode-extension/src/common/Project.ts +++ b/packages/vscode-extension/src/common/Project.ts @@ -78,7 +78,7 @@ export interface ProjectInterface { stepOverDebugger(): Promise; focusBuildOutput(): Promise; focusDebugConsole(): Promise; - + focusIntoSecondarySidebar(): Promise; openNavigation(navigationItemID: string): Promise; dispatchTouch(xRatio: number, yRatio: number, type: "Up" | "Move" | "Down"): Promise; diff --git a/packages/vscode-extension/src/common/WorkspaceConfig.ts b/packages/vscode-extension/src/common/WorkspaceConfig.ts new file mode 100644 index 000000000..6266182e6 --- /dev/null +++ b/packages/vscode-extension/src/common/WorkspaceConfig.ts @@ -0,0 +1,94 @@ +import { ConfigurationChangeEvent, workspace, Disposable } from "vscode"; +import { Tabpanel } from "../panels/Tabpanel"; +import { EventEmitter } from "stream"; +import { Logger } from "../Logger"; + +export type WorkspaceConfigProps = { + showPanelInActivityBar: boolean; + relativeAppLocation: string; +}; + +export interface WorkspaceConfigEventMap { + workspaceConfigChange: WorkspaceConfigProps; +} + +export interface WorkspaceConfigEventListener { + (event: T): void; +} + +export interface WorkspaceConfigInterface { + getWorkspaceConfigProps(): Promise; + addListener( + eventType: K, + listener: WorkspaceConfigEventListener + ): Promise; + removeListener( + eventType: K, + listener: WorkspaceConfigEventListener + ): Promise; +} + +export class WorkspaceConfig implements Disposable, WorkspaceConfigInterface { + public static currentWorkspaceConfig: WorkspaceConfig | undefined; + private workspaceConfigProps: WorkspaceConfigProps; + private eventEmitter = new EventEmitter(); + private workspaceConfigListener: Disposable | undefined; + + constructor() { + WorkspaceConfig.currentWorkspaceConfig = this; + this.workspaceConfigProps = { + showPanelInActivityBar: workspace + .getConfiguration("ReactNativeIDE") + .get("showPanelInActivityBar")!, + relativeAppLocation: workspace + .getConfiguration("ReactNativeIDE") + .get("relativeAppLocation")!, + }; + this.IDEPanelLocationListener(); + } + + private IDEPanelLocationListener() { + this.workspaceConfigListener = workspace.onDidChangeConfiguration( + (event: ConfigurationChangeEvent) => { + if (!event.affectsConfiguration("ReactNativeIDE")) { + return; + } + if (event.affectsConfiguration("ReactNativeIDE.showPanelInActivityBar")) { + this.workspaceConfigProps.showPanelInActivityBar = workspace + .getConfiguration("ReactNativeIDE") + .get("showPanelInActivityBar")!; + if (workspace.getConfiguration("ReactNativeIDE").get("showPanelInActivityBar")) { + Tabpanel.currentPanel?.dispose(); + } + } else if (event.affectsConfiguration("ReactNativeIDE.relativeAppLocation")) { + this.workspaceConfigProps.relativeAppLocation = workspace + .getConfiguration("ReactNativeIDE") + .get("relativeAppLocation")!; + } + this.eventEmitter.emit("workspaceConfigChange", this.workspaceConfigProps); + } + ); + } + + async getWorkspaceConfigProps(): Promise { + return this.workspaceConfigProps; + } + + async addListener( + eventType: K, + listener: WorkspaceConfigEventListener + ) { + this.eventEmitter.addListener(eventType, listener); + } + + async removeListener( + eventType: K, + listener: WorkspaceConfigEventListener + ) { + this.eventEmitter.removeListener(eventType, listener); + } + + dispose() { + this.workspaceConfigListener?.dispose(); + } +} diff --git a/packages/vscode-extension/src/panels/SidepanelViewProvider.ts b/packages/vscode-extension/src/panels/SidepanelViewProvider.ts index 1a11f301b..871e76e7f 100644 --- a/packages/vscode-extension/src/panels/SidepanelViewProvider.ts +++ b/packages/vscode-extension/src/panels/SidepanelViewProvider.ts @@ -1,6 +1,6 @@ import { ExtensionContext, Uri, WebviewView, WebviewViewProvider, commands } from "vscode"; import { generateWebviewContent } from "./webviewContentGenerator"; -import { extensionContext } from "../utilities/extensionContext"; + import { WebviewController } from "./WebviewController"; import { Logger } from "../Logger"; diff --git a/packages/vscode-extension/src/panels/WebviewController.ts b/packages/vscode-extension/src/panels/WebviewController.ts index 3892382f2..94c68e833 100644 --- a/packages/vscode-extension/src/panels/WebviewController.ts +++ b/packages/vscode-extension/src/panels/WebviewController.ts @@ -6,12 +6,14 @@ import { Project } from "../project/project"; import { openExternalUrl } from "../utilities/vsc"; import { Logger } from "../Logger"; import { extensionContext } from "../utilities/extensionContext"; +import { WorkspaceConfig } from "../common/WorkspaceConfig"; export class WebviewController implements Disposable { private readonly dependencyChecker: DependencyChecker; private readonly dependencyInstaller: DependencyInstaller; private readonly deviceManager: DeviceManager; public readonly project: Project; + public readonly workspaceConfig: WorkspaceConfig; private disposables: Disposable[] = []; private followEnabled = false; @@ -34,16 +36,20 @@ export class WebviewController implements Disposable { this.deviceManager = new DeviceManager(); this.project = new Project(this.deviceManager); + this.workspaceConfig = new WorkspaceConfig(); + this.disposables.push( this.dependencyChecker, this.dependencyInstaller, this.deviceManager, - this.project + this.project, + this.workspaceConfig ); this.callableObjects = new Map([ ["DeviceManager", this.deviceManager as object], ["Project", this.project as object], + ["WorkspaceConfig", this.workspaceConfig as object], ]); } diff --git a/packages/vscode-extension/src/project/project.ts b/packages/vscode-extension/src/project/project.ts index 9ca11f135..e5ab2a79e 100644 --- a/packages/vscode-extension/src/project/project.ts +++ b/packages/vscode-extension/src/project/project.ts @@ -261,16 +261,22 @@ export class Project implements Disposable, MetroDelegate, ProjectInterface { public async stepOverDebugger() { this.deviceSession?.stepOverDebugger(); } + public async focusBuildOutput() { if (!this.projectState.selectedDevice) { return; } this.buildManager.focusBuildOutput(); } + public async focusDebugConsole() { commands.executeCommand("workbench.panel.repl.view.focus"); } + public async focusIntoSecondarySidebar(): Promise { + commands.executeCommand("workbench.action.focusAuxiliaryBar"); + } + public async openNavigation(navigationItemID: string) { this.deviceSession?.openNavigation(navigationItemID); } diff --git a/packages/vscode-extension/src/webview/components/SettingsDropdown.tsx b/packages/vscode-extension/src/webview/components/SettingsDropdown.tsx index e8199f8dd..ee4ea817f 100644 --- a/packages/vscode-extension/src/webview/components/SettingsDropdown.tsx +++ b/packages/vscode-extension/src/webview/components/SettingsDropdown.tsx @@ -1,14 +1,12 @@ import React from "react"; import * as DropdownMenu from "@radix-ui/react-dropdown-menu"; - import "./shared/Dropdown.css"; import { useModal } from "../providers/ModalProvider"; - import DiagnosticView from "../views/DiagnosticView"; -import AndroidImagesView from "../views/AndroidImagesView"; import ManageDevicesView from "../views/ManageDevicesView"; import { ProjectInterface } from "../../common/Project"; import DoctorIcon from "./icons/DoctorIcon"; +import { useWorkspaceConfig } from "../providers/WorkspaceConfigProvider"; interface SettingsDropdownProps { children: React.ReactNode; @@ -17,6 +15,7 @@ interface SettingsDropdownProps { } function SettingsDropdown({ project, children, disabled }: SettingsDropdownProps) { + const { showPanelInActivityBar } = useWorkspaceConfig(); const { openModal } = useModal(); return ( @@ -62,6 +61,27 @@ function SettingsDropdown({ project, children, disabled }: SettingsDropdownProps Clean rebuild + + {showPanelInActivityBar && ( + <> + + { + project.focusIntoSecondarySidebar(); + openModal( + "Move to secondary sidebar", +
+ You can move extensions from Primary to secondary sidebar, by grab and droping + them.{" "} +
+ ); + }}> + + Move to secondary sidebar +
+ + )} diff --git a/packages/vscode-extension/src/webview/index.jsx b/packages/vscode-extension/src/webview/index.jsx index fa79bfb29..123b3b9a4 100644 --- a/packages/vscode-extension/src/webview/index.jsx +++ b/packages/vscode-extension/src/webview/index.jsx @@ -7,6 +7,7 @@ import DependenciesProvider from "./providers/DependenciesProvider"; import ModalProvider from "./providers/ModalProvider"; import ProjectProvider from "./providers/ProjectProvider"; import AlertProvider from "./providers/AlertProvider"; +import WorkspaceConfigProvider from "./providers/WorkspaceConfigProvider"; import "./styles/colors.css"; @@ -16,15 +17,17 @@ const root = createRoot(container); root.render( - - - - - - - - - + + + + + + + + + + + ); diff --git a/packages/vscode-extension/src/webview/providers/WorkspaceConfigProvider.tsx b/packages/vscode-extension/src/webview/providers/WorkspaceConfigProvider.tsx new file mode 100644 index 000000000..dc4346104 --- /dev/null +++ b/packages/vscode-extension/src/webview/providers/WorkspaceConfigProvider.tsx @@ -0,0 +1,41 @@ +import { PropsWithChildren, useContext, createContext, useState, useEffect } from "react"; +import { makeProxy } from "../utilities/rpc"; +import { WorkspaceConfigInterface, WorkspaceConfigProps } from "../../common/WorkspaceConfig"; + +const config = makeProxy("WorkspaceConfig"); + +const WorkspaceConfigContext = createContext({ + showPanelInActivityBar: false, + relativeAppLocation: "", +}); + +export default function WorkspaceConfigProvider({ children }: PropsWithChildren) { + const [workspaceConfig, setWorkspaceConfig] = useState({ + showPanelInActivityBar: false, + relativeAppLocation: "", + }); + + useEffect(() => { + config.getWorkspaceConfigProps().then(setWorkspaceConfig); + config.addListener("workspaceConfigChange", setWorkspaceConfig); + + return () => { + config.removeListener("workspaceConfigChange", setWorkspaceConfig); + }; + }, []); + + return ( + + {children} + + ); +} + +export function useWorkspaceConfig() { + const context = useContext(WorkspaceConfigContext); + + if (context === undefined) { + throw new Error("useWorkspaceConfig must be used within a WorkspaceConfigProvider"); + } + return context; +}