mirror of
https://github.com/farion1231/cc-switch.git
synced 2026-05-28 09:10:18 +08:00
- 恢复 Claude Desktop 共享功能入口
- 将 Claude Desktop 的 Prompts、Skills、Sessions 映射到 Claude Code 配置 - 恢复 Claude Desktop 顶部功能按钮组 - 继续复用统一 MCP 面板入口
This commit is contained in:
+190
-183
@@ -165,6 +165,8 @@ function App() {
|
||||
const queryClient = useQueryClient();
|
||||
|
||||
const [activeApp, setActiveApp] = useState<AppId>(getInitialApp);
|
||||
const sharedFeatureApp: AppId =
|
||||
activeApp === "claude-desktop" ? "claude" : activeApp;
|
||||
const [currentView, setCurrentView] = useState<View>(getInitialView);
|
||||
const [settingsDefaultTab, setSettingsDefaultTab] = useState("general");
|
||||
const [isAddOpen, setIsAddOpen] = useState(false);
|
||||
@@ -210,16 +212,16 @@ function App() {
|
||||
useEffect(() => {
|
||||
if (
|
||||
currentView === "sessions" &&
|
||||
activeApp !== "claude" &&
|
||||
activeApp !== "codex" &&
|
||||
activeApp !== "opencode" &&
|
||||
activeApp !== "openclaw" &&
|
||||
activeApp !== "gemini" &&
|
||||
activeApp !== "hermes"
|
||||
sharedFeatureApp !== "claude" &&
|
||||
sharedFeatureApp !== "codex" &&
|
||||
sharedFeatureApp !== "opencode" &&
|
||||
sharedFeatureApp !== "openclaw" &&
|
||||
sharedFeatureApp !== "gemini" &&
|
||||
sharedFeatureApp !== "hermes"
|
||||
) {
|
||||
setCurrentView("providers");
|
||||
}
|
||||
}, [activeApp, currentView]);
|
||||
}, [sharedFeatureApp, currentView]);
|
||||
|
||||
const [editingProvider, setEditingProvider] = useState<Provider | null>(null);
|
||||
const [usageProvider, setUsageProvider] = useState<Provider | null>(null);
|
||||
@@ -273,14 +275,14 @@ function App() {
|
||||
currentView === "openclawAgents");
|
||||
const { data: openclawHealthWarnings = [] } =
|
||||
useOpenClawHealth(isOpenClawView);
|
||||
const hasSkillsSupport = activeApp !== "claude-desktop";
|
||||
const hasSkillsSupport = sharedFeatureApp !== "openclaw";
|
||||
const hasSessionSupport =
|
||||
activeApp === "claude" ||
|
||||
activeApp === "codex" ||
|
||||
activeApp === "opencode" ||
|
||||
activeApp === "openclaw" ||
|
||||
activeApp === "gemini" ||
|
||||
activeApp === "hermes";
|
||||
sharedFeatureApp === "claude" ||
|
||||
sharedFeatureApp === "codex" ||
|
||||
sharedFeatureApp === "opencode" ||
|
||||
sharedFeatureApp === "openclaw" ||
|
||||
sharedFeatureApp === "gemini" ||
|
||||
sharedFeatureApp === "hermes";
|
||||
|
||||
const {
|
||||
addProvider,
|
||||
@@ -911,7 +913,7 @@ function App() {
|
||||
ref={promptPanelRef}
|
||||
open={true}
|
||||
onOpenChange={() => setCurrentView("providers")}
|
||||
appId={activeApp}
|
||||
appId={sharedFeatureApp}
|
||||
/>
|
||||
);
|
||||
case "hermesMemory":
|
||||
@@ -921,14 +923,18 @@ function App() {
|
||||
<UnifiedSkillsPanel
|
||||
ref={unifiedSkillsPanelRef}
|
||||
onOpenDiscovery={() => setCurrentView("skillsDiscovery")}
|
||||
currentApp={activeApp === "openclaw" ? "claude" : activeApp}
|
||||
currentApp={
|
||||
sharedFeatureApp === "openclaw" ? "claude" : sharedFeatureApp
|
||||
}
|
||||
/>
|
||||
);
|
||||
case "skillsDiscovery":
|
||||
return (
|
||||
<SkillsPage
|
||||
ref={skillsPageRef}
|
||||
initialApp={activeApp === "openclaw" ? "claude" : activeApp}
|
||||
initialApp={
|
||||
sharedFeatureApp === "openclaw" ? "claude" : sharedFeatureApp
|
||||
}
|
||||
/>
|
||||
);
|
||||
case "mcp":
|
||||
@@ -950,7 +956,12 @@ function App() {
|
||||
);
|
||||
|
||||
case "sessions":
|
||||
return <SessionManagerPage key={activeApp} appId={activeApp} />;
|
||||
return (
|
||||
<SessionManagerPage
|
||||
key={sharedFeatureApp}
|
||||
appId={sharedFeatureApp}
|
||||
/>
|
||||
);
|
||||
case "workspace":
|
||||
return <WorkspaceFilesPanel />;
|
||||
case "openclawEnv":
|
||||
@@ -1163,7 +1174,9 @@ function App() {
|
||||
<h1 className="text-lg font-semibold">
|
||||
{currentView === "settings" && t("settings.title")}
|
||||
{currentView === "prompts" &&
|
||||
t("prompts.title", { appName: t(`apps.${activeApp}`) })}
|
||||
t("prompts.title", {
|
||||
appName: t(`apps.${sharedFeatureApp}`),
|
||||
})}
|
||||
{currentView === "skills" && t("skills.title")}
|
||||
{currentView === "skillsDiscovery" && t("skills.title")}
|
||||
{currentView === "mcp" && t("mcp.unifiedPanel.title")}
|
||||
@@ -1376,170 +1389,164 @@ function App() {
|
||||
compact={isToolbarCompact}
|
||||
/>
|
||||
|
||||
{activeApp !== "claude-desktop" && (
|
||||
<div className="flex items-center gap-1 p-1 bg-muted rounded-xl">
|
||||
<AnimatePresence mode="wait">
|
||||
<motion.div
|
||||
key={
|
||||
activeApp === "openclaw"
|
||||
? "openclaw"
|
||||
: activeApp === "hermes"
|
||||
? "hermes"
|
||||
: "default"
|
||||
}
|
||||
className="flex items-center gap-1"
|
||||
initial={{ opacity: 0 }}
|
||||
animate={{ opacity: 1 }}
|
||||
exit={{ opacity: 0 }}
|
||||
transition={{ duration: 0.15 }}
|
||||
>
|
||||
{activeApp === "hermes" ? (
|
||||
<>
|
||||
<Button
|
||||
variant="ghost"
|
||||
size="sm"
|
||||
onClick={() => setCurrentView("skills")}
|
||||
className="text-muted-foreground hover:text-foreground hover:bg-black/5 dark:hover:bg-white/5 w-8 px-2"
|
||||
title={t("skills.manage")}
|
||||
>
|
||||
<Wrench className="w-4 h-4" />
|
||||
</Button>
|
||||
<Button
|
||||
variant="ghost"
|
||||
size="sm"
|
||||
onClick={() => setCurrentView("hermesMemory")}
|
||||
className="text-muted-foreground hover:text-foreground hover:bg-black/5 dark:hover:bg-white/5 w-8 px-2"
|
||||
title={t("hermes.memory.title")}
|
||||
>
|
||||
<Brain className="w-4 h-4" />
|
||||
</Button>
|
||||
<Button
|
||||
variant="ghost"
|
||||
size="sm"
|
||||
onClick={() => void openHermesWebUI()}
|
||||
className="text-muted-foreground hover:text-foreground hover:bg-black/5 dark:hover:bg-white/5 w-8 px-2"
|
||||
title={t("hermes.webui.open")}
|
||||
>
|
||||
<LayoutDashboard className="w-4 h-4" />
|
||||
</Button>
|
||||
<Button
|
||||
variant="ghost"
|
||||
size="sm"
|
||||
onClick={() => setCurrentView("mcp")}
|
||||
className="text-muted-foreground hover:text-foreground hover:bg-black/5 dark:hover:bg-white/5 w-8 px-2"
|
||||
title={t("mcp.title")}
|
||||
>
|
||||
<McpIcon size={16} />
|
||||
</Button>
|
||||
</>
|
||||
) : activeApp === "openclaw" ? (
|
||||
<>
|
||||
<Button
|
||||
variant="ghost"
|
||||
size="sm"
|
||||
onClick={() => setCurrentView("workspace")}
|
||||
className="text-muted-foreground hover:text-foreground hover:bg-black/5 dark:hover:bg-white/5 w-8 px-2"
|
||||
title={t("workspace.manage")}
|
||||
>
|
||||
<FolderOpen className="w-4 h-4" />
|
||||
</Button>
|
||||
<Button
|
||||
variant="ghost"
|
||||
size="sm"
|
||||
onClick={() => setCurrentView("openclawEnv")}
|
||||
className="text-muted-foreground hover:text-foreground hover:bg-black/5 dark:hover:bg-white/5 w-8 px-2"
|
||||
title={t("openclaw.env.title")}
|
||||
>
|
||||
<KeyRound className="w-4 h-4" />
|
||||
</Button>
|
||||
<Button
|
||||
variant="ghost"
|
||||
size="sm"
|
||||
onClick={() =>
|
||||
setCurrentView("openclawTools")
|
||||
}
|
||||
className="text-muted-foreground hover:text-foreground hover:bg-black/5 dark:hover:bg-white/5 w-8 px-2"
|
||||
title={t("openclaw.tools.title")}
|
||||
>
|
||||
<Shield className="w-4 h-4" />
|
||||
</Button>
|
||||
<Button
|
||||
variant="ghost"
|
||||
size="sm"
|
||||
onClick={() =>
|
||||
setCurrentView("openclawAgents")
|
||||
}
|
||||
className="text-muted-foreground hover:text-foreground hover:bg-black/5 dark:hover:bg-white/5 w-8 px-2"
|
||||
title={t("openclaw.agents.title")}
|
||||
>
|
||||
<Cpu className="w-4 h-4" />
|
||||
</Button>
|
||||
<Button
|
||||
variant="ghost"
|
||||
size="sm"
|
||||
onClick={() => setCurrentView("sessions")}
|
||||
className="text-muted-foreground hover:text-foreground hover:bg-black/5 dark:hover:bg-white/5 w-8 px-2"
|
||||
title={t("sessionManager.title")}
|
||||
>
|
||||
<History className="w-4 h-4" />
|
||||
</Button>
|
||||
</>
|
||||
) : (
|
||||
<>
|
||||
<Button
|
||||
variant="ghost"
|
||||
size="sm"
|
||||
onClick={() => setCurrentView("skills")}
|
||||
className={cn(
|
||||
"text-muted-foreground hover:text-foreground hover:bg-black/5 dark:hover:bg-white/5",
|
||||
"transition-all duration-200 ease-in-out overflow-hidden",
|
||||
hasSkillsSupport
|
||||
? "opacity-100 w-8 scale-100 px-2"
|
||||
: "opacity-0 w-0 scale-75 pointer-events-none px-0 -ml-1",
|
||||
)}
|
||||
title={t("skills.manage")}
|
||||
>
|
||||
<Wrench className="flex-shrink-0 w-4 h-4" />
|
||||
</Button>
|
||||
<Button
|
||||
variant="ghost"
|
||||
size="sm"
|
||||
onClick={() => setCurrentView("prompts")}
|
||||
className="text-muted-foreground hover:text-foreground hover:bg-black/5 dark:hover:bg-white/5 w-8 px-2"
|
||||
title={t("prompts.manage")}
|
||||
>
|
||||
<Book className="w-4 h-4" />
|
||||
</Button>
|
||||
<Button
|
||||
variant="ghost"
|
||||
size="sm"
|
||||
onClick={() => setCurrentView("sessions")}
|
||||
className={cn(
|
||||
"text-muted-foreground hover:text-foreground hover:bg-black/5 dark:hover:bg-white/5",
|
||||
"transition-all duration-200 ease-in-out overflow-hidden",
|
||||
hasSessionSupport
|
||||
? "opacity-100 w-8 scale-100 px-2"
|
||||
: "opacity-0 w-0 scale-75 pointer-events-none px-0 -ml-1",
|
||||
)}
|
||||
title={t("sessionManager.title")}
|
||||
>
|
||||
<History className="flex-shrink-0 w-4 h-4" />
|
||||
</Button>
|
||||
<Button
|
||||
variant="ghost"
|
||||
size="sm"
|
||||
onClick={() => setCurrentView("mcp")}
|
||||
className="text-muted-foreground hover:text-foreground hover:bg-black/5 dark:hover:bg-white/5 w-8 px-2"
|
||||
title={t("mcp.title")}
|
||||
>
|
||||
<McpIcon size={16} />
|
||||
</Button>
|
||||
</>
|
||||
)}
|
||||
</motion.div>
|
||||
</AnimatePresence>
|
||||
</div>
|
||||
)}
|
||||
<div className="flex items-center gap-1 p-1 bg-muted rounded-xl">
|
||||
<AnimatePresence mode="wait">
|
||||
<motion.div
|
||||
key={
|
||||
activeApp === "openclaw"
|
||||
? "openclaw"
|
||||
: activeApp === "hermes"
|
||||
? "hermes"
|
||||
: "default"
|
||||
}
|
||||
className="flex items-center gap-1"
|
||||
initial={{ opacity: 0 }}
|
||||
animate={{ opacity: 1 }}
|
||||
exit={{ opacity: 0 }}
|
||||
transition={{ duration: 0.15 }}
|
||||
>
|
||||
{activeApp === "hermes" ? (
|
||||
<>
|
||||
<Button
|
||||
variant="ghost"
|
||||
size="sm"
|
||||
onClick={() => setCurrentView("skills")}
|
||||
className="text-muted-foreground hover:text-foreground hover:bg-black/5 dark:hover:bg-white/5 w-8 px-2"
|
||||
title={t("skills.manage")}
|
||||
>
|
||||
<Wrench className="w-4 h-4" />
|
||||
</Button>
|
||||
<Button
|
||||
variant="ghost"
|
||||
size="sm"
|
||||
onClick={() => setCurrentView("hermesMemory")}
|
||||
className="text-muted-foreground hover:text-foreground hover:bg-black/5 dark:hover:bg-white/5 w-8 px-2"
|
||||
title={t("hermes.memory.title")}
|
||||
>
|
||||
<Brain className="w-4 h-4" />
|
||||
</Button>
|
||||
<Button
|
||||
variant="ghost"
|
||||
size="sm"
|
||||
onClick={() => void openHermesWebUI()}
|
||||
className="text-muted-foreground hover:text-foreground hover:bg-black/5 dark:hover:bg-white/5 w-8 px-2"
|
||||
title={t("hermes.webui.open")}
|
||||
>
|
||||
<LayoutDashboard className="w-4 h-4" />
|
||||
</Button>
|
||||
<Button
|
||||
variant="ghost"
|
||||
size="sm"
|
||||
onClick={() => setCurrentView("mcp")}
|
||||
className="text-muted-foreground hover:text-foreground hover:bg-black/5 dark:hover:bg-white/5 w-8 px-2"
|
||||
title={t("mcp.title")}
|
||||
>
|
||||
<McpIcon size={16} />
|
||||
</Button>
|
||||
</>
|
||||
) : activeApp === "openclaw" ? (
|
||||
<>
|
||||
<Button
|
||||
variant="ghost"
|
||||
size="sm"
|
||||
onClick={() => setCurrentView("workspace")}
|
||||
className="text-muted-foreground hover:text-foreground hover:bg-black/5 dark:hover:bg-white/5 w-8 px-2"
|
||||
title={t("workspace.manage")}
|
||||
>
|
||||
<FolderOpen className="w-4 h-4" />
|
||||
</Button>
|
||||
<Button
|
||||
variant="ghost"
|
||||
size="sm"
|
||||
onClick={() => setCurrentView("openclawEnv")}
|
||||
className="text-muted-foreground hover:text-foreground hover:bg-black/5 dark:hover:bg-white/5 w-8 px-2"
|
||||
title={t("openclaw.env.title")}
|
||||
>
|
||||
<KeyRound className="w-4 h-4" />
|
||||
</Button>
|
||||
<Button
|
||||
variant="ghost"
|
||||
size="sm"
|
||||
onClick={() => setCurrentView("openclawTools")}
|
||||
className="text-muted-foreground hover:text-foreground hover:bg-black/5 dark:hover:bg-white/5 w-8 px-2"
|
||||
title={t("openclaw.tools.title")}
|
||||
>
|
||||
<Shield className="w-4 h-4" />
|
||||
</Button>
|
||||
<Button
|
||||
variant="ghost"
|
||||
size="sm"
|
||||
onClick={() => setCurrentView("openclawAgents")}
|
||||
className="text-muted-foreground hover:text-foreground hover:bg-black/5 dark:hover:bg-white/5 w-8 px-2"
|
||||
title={t("openclaw.agents.title")}
|
||||
>
|
||||
<Cpu className="w-4 h-4" />
|
||||
</Button>
|
||||
<Button
|
||||
variant="ghost"
|
||||
size="sm"
|
||||
onClick={() => setCurrentView("sessions")}
|
||||
className="text-muted-foreground hover:text-foreground hover:bg-black/5 dark:hover:bg-white/5 w-8 px-2"
|
||||
title={t("sessionManager.title")}
|
||||
>
|
||||
<History className="w-4 h-4" />
|
||||
</Button>
|
||||
</>
|
||||
) : (
|
||||
<>
|
||||
<Button
|
||||
variant="ghost"
|
||||
size="sm"
|
||||
onClick={() => setCurrentView("skills")}
|
||||
className={cn(
|
||||
"text-muted-foreground hover:text-foreground hover:bg-black/5 dark:hover:bg-white/5",
|
||||
"transition-all duration-200 ease-in-out overflow-hidden",
|
||||
hasSkillsSupport
|
||||
? "opacity-100 w-8 scale-100 px-2"
|
||||
: "opacity-0 w-0 scale-75 pointer-events-none px-0 -ml-1",
|
||||
)}
|
||||
title={t("skills.manage")}
|
||||
>
|
||||
<Wrench className="flex-shrink-0 w-4 h-4" />
|
||||
</Button>
|
||||
<Button
|
||||
variant="ghost"
|
||||
size="sm"
|
||||
onClick={() => setCurrentView("prompts")}
|
||||
className="text-muted-foreground hover:text-foreground hover:bg-black/5 dark:hover:bg-white/5 w-8 px-2"
|
||||
title={t("prompts.manage")}
|
||||
>
|
||||
<Book className="w-4 h-4" />
|
||||
</Button>
|
||||
<Button
|
||||
variant="ghost"
|
||||
size="sm"
|
||||
onClick={() => setCurrentView("sessions")}
|
||||
className={cn(
|
||||
"text-muted-foreground hover:text-foreground hover:bg-black/5 dark:hover:bg-white/5",
|
||||
"transition-all duration-200 ease-in-out overflow-hidden",
|
||||
hasSessionSupport
|
||||
? "opacity-100 w-8 scale-100 px-2"
|
||||
: "opacity-0 w-0 scale-75 pointer-events-none px-0 -ml-1",
|
||||
)}
|
||||
title={t("sessionManager.title")}
|
||||
>
|
||||
<History className="flex-shrink-0 w-4 h-4" />
|
||||
</Button>
|
||||
<Button
|
||||
variant="ghost"
|
||||
size="sm"
|
||||
onClick={() => setCurrentView("mcp")}
|
||||
className="text-muted-foreground hover:text-foreground hover:bg-black/5 dark:hover:bg-white/5 w-8 px-2"
|
||||
title={t("mcp.title")}
|
||||
>
|
||||
<McpIcon size={16} />
|
||||
</Button>
|
||||
</>
|
||||
)}
|
||||
</motion.div>
|
||||
</AnimatePresence>
|
||||
</div>
|
||||
|
||||
<Button
|
||||
onClick={() => setIsAddOpen(true)}
|
||||
|
||||
Reference in New Issue
Block a user