mirror of
https://github.com/cline/cline.git
synced 2026-09-21 05:10:09 +08:00
feat: adds navigation bar component and restructure app layout (#5220)
This commit is contained in:
@@ -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>
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
@@ -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}
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user