feat: adds navigation bar component and restructure app layout (#5220)

This commit is contained in:
Bee
2025-07-29 13:05:01 -04:00
committed by GitHub
parent 6cbfb2b8b0
commit c54f0da737
4 changed files with 105 additions and 43 deletions
+2 -2
View File
@@ -58,7 +58,7 @@ const AppContent = () => {
}
return (
<>
<div className="flex h-full w-full">
{showSettings && <SettingsView onDone={hideSettings} />}
{showHistory && <HistoryView onDone={hideHistory} />}
{showMcp && <McpView initialTab={mcpTab} onDone={closeMcpView} />}
@@ -77,7 +77,7 @@ const AppContent = () => {
showAnnouncement={showAnnouncement}
hideAnnouncement={hideAnnouncement}
/>
</>
</div>
)
}
+20 -17
View File
@@ -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 (
<ChatLayout isHidden={isHidden}>
{IS_STANDALONE && <Navbar />}
{task ? (
<TaskSection
task={task}
+61
View File
@@ -0,0 +1,61 @@
import { DatabaseIcon, HistoryIcon, PlusIcon, SettingsIcon, UserCircleIcon } from "lucide-react"
import { useMemo } from "react"
import { useExtensionState } from "../../context/ExtensionStateContext"
import { TabTrigger } from "../common/Tab"
export const Navbar = () => {
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 (
<nav
id="cline-navbar-container"
className="fixed top-0 right-2 inline-flex justify-end bg-transparent shadow-sm max-h-[20px] w-full gap-2 mb-1 z-10 border-none items-center">
{SETTINGS_TABS.map((tab) => (
<TabTrigger
key={`navbar-trigger-${tab.id}`}
value={tab.id}
className="bg-transparent border-none text-white m-0 p-0 cursor-pointer"
data-testid={`tab-${tab.id}`}
onSelect={() => tab.navigate()}>
<tab.icon className="text-white" strokeWidth={1} size={18} />
</TabTrigger>
))}
</nav>
)
}
@@ -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