From c54f0da7378b9d11b393614ad0bb420531716a5b Mon Sep 17 00:00:00 2001 From: Bee <68532117+abeatrix@users.noreply.github.com> Date: Tue, 29 Jul 2025 10:05:01 -0700 Subject: [PATCH] feat: adds navigation bar component and restructure app layout (#5220) --- webview-ui/src/App.tsx | 4 +- webview-ui/src/components/chat/ChatView.tsx | 37 +++++------ webview-ui/src/components/menu/Navbar.tsx | 61 +++++++++++++++++++ .../src/context/ExtensionStateContext.tsx | 46 +++++++------- 4 files changed, 105 insertions(+), 43 deletions(-) create mode 100644 webview-ui/src/components/menu/Navbar.tsx diff --git a/webview-ui/src/App.tsx b/webview-ui/src/App.tsx index 9c2df12e73..9de0a605d3 100644 --- a/webview-ui/src/App.tsx +++ b/webview-ui/src/App.tsx @@ -58,7 +58,7 @@ const AppContent = () => { } return ( - <> +
{showSettings && } {showHistory && } {showMcp && } @@ -77,7 +77,7 @@ const AppContent = () => { showAnnouncement={showAnnouncement} hideAnnouncement={hideAnnouncement} /> - +
) } diff --git a/webview-ui/src/components/chat/ChatView.tsx b/webview-ui/src/components/chat/ChatView.tsx index 531c609fdb..b444671038 100644 --- a/webview-ui/src/components/chat/ChatView.tsx +++ b/webview-ui/src/components/chat/ChatView.tsx @@ -1,32 +1,32 @@ -import { useCallback, useEffect, useMemo } from "react" -import { useMount } from "react-use" -import { ClineApiReqInfo, ClineMessage } from "@shared/ExtensionMessage" import { findLast } from "@shared/array" import { combineApiRequests } from "@shared/combineApiRequests" import { combineCommandSequences } from "@shared/combineCommandSequences" +import type { ClineApiReqInfo, ClineMessage } from "@shared/ExtensionMessage" import { getApiMetrics } from "@shared/getApiMetrics" +import { BooleanRequest, EmptyRequest, StringRequest } from "@shared/proto/cline/common" +import { useCallback, useEffect, useMemo } from "react" +import { useMount } from "react-use" +import { normalizeApiConfiguration } from "@/components/settings/utils/providerUtils" import { useExtensionState } from "@/context/ExtensionStateContext" import { FileServiceClient, UiServiceClient } from "@/services/grpc-client" -import { normalizeApiConfiguration } from "@/components/settings/utils/providerUtils" -import { BooleanRequest, EmptyRequest, StringRequest } from "@shared/proto/cline/common" - +import { Navbar } from "../menu/Navbar" // Import utilities and hooks from the new structure import { + ActionButtons, + CHAT_CONSTANTS, + ChatLayout, convertHtmlToMarkdown, filterVisibleMessages, groupMessages, - CHAT_CONSTANTS, - useChatState, - useButtonState, - useScrollBehavior, - useMessageHandlers, - useIsStreaming, - ChatLayout, - WelcomeSection, - TaskSection, - MessagesArea, - ActionButtons, InputSection, + MessagesArea, + TaskSection, + useButtonState, + useChatState, + useIsStreaming, + useMessageHandlers, + useScrollBehavior, + WelcomeSection, } from "./chat-view" interface ChatViewProps { @@ -39,6 +39,8 @@ interface ChatViewProps { // Use constants from the imported module const MAX_IMAGES_AND_FILES_PER_MESSAGE = CHAT_CONSTANTS.MAX_IMAGES_AND_FILES_PER_MESSAGE +const IS_STANDALONE = window?.__is_standalone__ ?? false + const ChatView = ({ isHidden, showAnnouncement, hideAnnouncement, showHistoryView }: ChatViewProps) => { const { version, @@ -321,6 +323,7 @@ const ChatView = ({ isHidden, showAnnouncement, hideAnnouncement, showHistoryVie return ( + {IS_STANDALONE && } {task ? ( { + const { navigateToHistory, navigateToSettings, navigateToAccount, navigateToMcp, navigateToChat } = useExtensionState() + + const SETTINGS_TABS = useMemo( + () => [ + { + id: "chat", + name: "Chat", + icon: PlusIcon, + navigate: navigateToChat, + }, + { + id: "mcp", + name: "MCP", + icon: DatabaseIcon, + navigate: navigateToMcp, + }, + { + id: "history", + name: "History", + icon: HistoryIcon, + navigate: navigateToHistory, + }, + { + id: "account", + name: "Account", + icon: UserCircleIcon, + navigate: navigateToAccount, + }, + { + id: "settings", + name: "Settings", + icon: SettingsIcon, + navigate: navigateToSettings, + }, + ], + [navigateToAccount, navigateToChat, navigateToHistory, navigateToMcp, navigateToSettings], + ) + + return ( + + ) +} diff --git a/webview-ui/src/context/ExtensionStateContext.tsx b/webview-ui/src/context/ExtensionStateContext.tsx index f8bb1b3c5f..57227621ff 100644 --- a/webview-ui/src/context/ExtensionStateContext.tsx +++ b/webview-ui/src/context/ExtensionStateContext.tsx @@ -1,39 +1,37 @@ -import React, { createContext, useCallback, useContext, useEffect, useRef, useState } from "react" +import type React from "react" +import { createContext, useCallback, useContext, useEffect, useRef, useState } from "react" import "../../../src/shared/webview/types" -import { - StateServiceClient, - ModelsServiceClient, - UiServiceClient, - FileServiceClient, - McpServiceClient, -} from "../services/grpc-client" +import { DEFAULT_AUTO_APPROVAL_SETTINGS } from "@shared/AutoApprovalSettings" +import { findLastIndex } from "@shared/array" +import { DEFAULT_BROWSER_SETTINGS } from "@shared/BrowserSettings" +import { type ChatSettings, DEFAULT_CHAT_SETTINGS } from "@shared/ChatSettings" +import { DEFAULT_PLATFORM, type ExtensionState } from "@shared/ExtensionMessage" +import { DEFAULT_MCP_DISPLAY_MODE } from "@shared/McpDisplayMode" +import type { UserInfo } from "@shared/proto/cline/account" import { EmptyRequest, StringRequest } from "@shared/proto/cline/common" -import { UpdateSettingsRequest } from "@shared/proto/cline/state" +import type { OpenRouterCompatibleModelInfo } from "@shared/proto/cline/models" +import { type TerminalProfile, UpdateSettingsRequest } from "@shared/proto/cline/state" import { WebviewProviderType as WebviewProviderTypeEnum, WebviewProviderTypeRequest } from "@shared/proto/cline/ui" -import { TerminalProfile } from "@shared/proto/cline/state" import { convertProtoToClineMessage } from "@shared/proto-conversions/cline-message" import { convertProtoMcpServersToMcpServers } from "@shared/proto-conversions/mcp/mcp-server-conversion" -import { DEFAULT_AUTO_APPROVAL_SETTINGS } from "@shared/AutoApprovalSettings" -import { DEFAULT_BROWSER_SETTINGS } from "@shared/BrowserSettings" -import { ChatSettings, DEFAULT_CHAT_SETTINGS } from "@shared/ChatSettings" -import { DEFAULT_PLATFORM, ExtensionState } from "@shared/ExtensionMessage" -import { findLastIndex } from "@shared/array" import { - ModelInfo, + groqDefaultModelId, + groqModels, + type ModelInfo, openRouterDefaultModelId, openRouterDefaultModelInfo, requestyDefaultModelId, requestyDefaultModelInfo, - groqDefaultModelId, - groqModels, - huggingFaceDefaultModelId, - huggingFaceModels, } from "../../../src/shared/api" -import { McpMarketplaceCatalog, McpServer, McpViewTab } from "../../../src/shared/mcp" +import type { McpMarketplaceCatalog, McpServer, McpViewTab } from "../../../src/shared/mcp" +import { + FileServiceClient, + McpServiceClient, + ModelsServiceClient, + StateServiceClient, + UiServiceClient, +} from "../services/grpc-client" import { convertTextMateToHljs } from "../utils/textMateToHljs" -import { OpenRouterCompatibleModelInfo } from "@shared/proto/cline/models" -import { UserInfo } from "@shared/proto/cline/account" -import { DEFAULT_MCP_DISPLAY_MODE } from "@shared/McpDisplayMode" interface ExtensionStateContextType extends ExtensionState { didHydrateState: boolean