mirror of
https://github.com/farion1231/cc-switch.git
synced 2026-07-25 13:45:03 +08:00
f0e8ba1d8f
* feat: init session manger * feat: persist selected app to localStorage - Save app selection when switching providers - Restore last selected app on page load * feat: persist current view to localStorage - Save view selection when switching tabs - Restore last selected view on page load * styles: update ui * feat: Improve macOS Terminal activation and refactor Kitty launch to use command with user's default shell. * fix: session view * feat: toc * feat: Implement FlexSearch for improved session search functionality. * feat: Redesign session manager search and filter UI for a more compact and dynamic experience. * refactor: modularize session manager by extracting components and utility functions into dedicated files. * feat: Enhance session terminal launching with support for iTerm2, Ghostty, WezTerm, and Alacritty, including UI and custom configuration options. * feat: Conditionally render terminal selection and resume session buttons only on macOS.
70 lines
1.9 KiB
TypeScript
70 lines
1.9 KiB
TypeScript
import type { AppId } from "@/lib/api";
|
|
import type { VisibleApps } from "@/types";
|
|
import { ProviderIcon } from "@/components/ProviderIcon";
|
|
|
|
interface AppSwitcherProps {
|
|
activeApp: AppId;
|
|
onSwitch: (app: AppId) => void;
|
|
visibleApps?: VisibleApps;
|
|
compact?: boolean;
|
|
}
|
|
|
|
const ALL_APPS: AppId[] = ["claude", "codex", "gemini", "opencode"];
|
|
const STORAGE_KEY = "cc-switch-last-app";
|
|
|
|
export function AppSwitcher({
|
|
activeApp,
|
|
onSwitch,
|
|
visibleApps,
|
|
compact,
|
|
}: AppSwitcherProps) {
|
|
const handleSwitch = (app: AppId) => {
|
|
if (app === activeApp) return;
|
|
localStorage.setItem(STORAGE_KEY, app);
|
|
onSwitch(app);
|
|
};
|
|
const iconSize = 20;
|
|
const appIconName: Record<AppId, string> = {
|
|
claude: "claude",
|
|
codex: "openai",
|
|
gemini: "gemini",
|
|
opencode: "opencode",
|
|
};
|
|
const appDisplayName: Record<AppId, string> = {
|
|
claude: "Claude",
|
|
codex: "Codex",
|
|
gemini: "Gemini",
|
|
opencode: "OpenCode",
|
|
};
|
|
|
|
// Filter apps based on visibility settings (default all visible)
|
|
const appsToShow = ALL_APPS.filter((app) => {
|
|
if (!visibleApps) return true;
|
|
return visibleApps[app];
|
|
});
|
|
|
|
return (
|
|
<div className="inline-flex bg-muted rounded-xl p-1 gap-1">
|
|
{appsToShow.map((app) => (
|
|
<button
|
|
key={app}
|
|
type="button"
|
|
onClick={() => handleSwitch(app)}
|
|
className={`group inline-flex items-center gap-2 px-3 h-8 rounded-md text-sm font-medium transition-all duration-200 ${
|
|
activeApp === app
|
|
? "bg-background text-foreground shadow-sm"
|
|
: "text-muted-foreground hover:text-foreground hover:bg-background/50"
|
|
}`}
|
|
>
|
|
<ProviderIcon
|
|
icon={appIconName[app]}
|
|
name={appDisplayName[app]}
|
|
size={iconSize}
|
|
/>
|
|
{!compact && <span>{appDisplayName[app]}</span>}
|
|
</button>
|
|
))}
|
|
</div>
|
|
);
|
|
}
|