mirror of
https://github.com/farion1231/cc-switch.git
synced 2026-03-27 21:39:58 +08:00
feat(settings): set Gemini visibility to false by default
New users will see Claude, Codex, and OpenCode by default, with Gemini hidden.
This commit is contained in:
118
src/components/settings/AppVisibilitySettings.tsx
Normal file
118
src/components/settings/AppVisibilitySettings.tsx
Normal file
@@ -0,0 +1,118 @@
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { Button } from "@/components/ui/button";
|
||||
import { cn } from "@/lib/utils";
|
||||
import { ProviderIcon } from "@/components/ProviderIcon";
|
||||
import type { SettingsFormState } from "@/hooks/useSettings";
|
||||
import type { VisibleApps } from "@/types";
|
||||
import type { AppId } from "@/lib/api";
|
||||
|
||||
interface AppVisibilitySettingsProps {
|
||||
settings: SettingsFormState;
|
||||
onChange: (updates: Partial<SettingsFormState>) => void;
|
||||
}
|
||||
|
||||
const APP_CONFIG: Array<{
|
||||
id: AppId;
|
||||
icon: string;
|
||||
nameKey: string;
|
||||
}> = [
|
||||
{ id: "claude", icon: "claude", nameKey: "apps.claude" },
|
||||
{ id: "codex", icon: "openai", nameKey: "apps.codex" },
|
||||
{ id: "gemini", icon: "gemini", nameKey: "apps.gemini" },
|
||||
{ id: "opencode", icon: "opencode", nameKey: "apps.opencode" },
|
||||
];
|
||||
|
||||
export function AppVisibilitySettings({ settings, onChange }: AppVisibilitySettingsProps) {
|
||||
const { t } = useTranslation();
|
||||
|
||||
const visibleApps: VisibleApps = settings.visibleApps ?? {
|
||||
claude: true,
|
||||
codex: true,
|
||||
gemini: false,
|
||||
opencode: true,
|
||||
};
|
||||
|
||||
// Count how many apps are currently visible
|
||||
const visibleCount = Object.values(visibleApps).filter(Boolean).length;
|
||||
|
||||
const handleToggle = (appId: AppId) => {
|
||||
const isCurrentlyVisible = visibleApps[appId];
|
||||
// Prevent disabling the last visible app
|
||||
if (isCurrentlyVisible && visibleCount <= 1) return;
|
||||
|
||||
onChange({
|
||||
visibleApps: {
|
||||
...visibleApps,
|
||||
[appId]: !isCurrentlyVisible,
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
return (
|
||||
<section className="space-y-2">
|
||||
<header className="space-y-1">
|
||||
<h3 className="text-sm font-medium">{t("settings.appVisibility.title")}</h3>
|
||||
<p className="text-xs text-muted-foreground">
|
||||
{t("settings.appVisibility.description")}
|
||||
</p>
|
||||
</header>
|
||||
<div className="inline-flex gap-1 rounded-md border border-border-default bg-background p-1">
|
||||
{APP_CONFIG.map((app) => {
|
||||
const isVisible = visibleApps[app.id];
|
||||
// Disable button if this is the last visible app
|
||||
const isDisabled = isVisible && visibleCount <= 1;
|
||||
|
||||
return (
|
||||
<AppButton
|
||||
key={app.id}
|
||||
active={isVisible}
|
||||
disabled={isDisabled}
|
||||
onClick={() => handleToggle(app.id)}
|
||||
icon={app.icon}
|
||||
name={t(app.nameKey)}
|
||||
>
|
||||
{t(app.nameKey)}
|
||||
</AppButton>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
</section>
|
||||
);
|
||||
}
|
||||
|
||||
interface AppButtonProps {
|
||||
active: boolean;
|
||||
disabled?: boolean;
|
||||
onClick: () => void;
|
||||
icon: string;
|
||||
name: string;
|
||||
children: React.ReactNode;
|
||||
}
|
||||
|
||||
function AppButton({
|
||||
active,
|
||||
disabled,
|
||||
onClick,
|
||||
icon,
|
||||
name,
|
||||
children,
|
||||
}: AppButtonProps) {
|
||||
return (
|
||||
<Button
|
||||
type="button"
|
||||
onClick={onClick}
|
||||
disabled={disabled}
|
||||
size="sm"
|
||||
variant={active ? "default" : "ghost"}
|
||||
className={cn(
|
||||
"w-[90px] gap-1.5",
|
||||
active
|
||||
? "shadow-sm"
|
||||
: "text-muted-foreground hover:text-foreground hover:bg-muted",
|
||||
)}
|
||||
>
|
||||
<ProviderIcon icon={icon} name={name} size={14} />
|
||||
{children}
|
||||
</Button>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user