From 30009ad5f120ca61fb100d29a27352091e52c967 Mon Sep 17 00:00:00 2001 From: Jason Date: Tue, 20 Jan 2026 12:28:45 +0800 Subject: [PATCH] feat(settings): set Gemini visibility to false by default New users will see Claude, Codex, and OpenCode by default, with Gemini hidden. --- .../settings/AppVisibilitySettings.tsx | 118 ++++++++++++++++++ 1 file changed, 118 insertions(+) create mode 100644 src/components/settings/AppVisibilitySettings.tsx diff --git a/src/components/settings/AppVisibilitySettings.tsx b/src/components/settings/AppVisibilitySettings.tsx new file mode 100644 index 00000000..a610c3a1 --- /dev/null +++ b/src/components/settings/AppVisibilitySettings.tsx @@ -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) => 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 ( +
+
+

{t("settings.appVisibility.title")}

+

+ {t("settings.appVisibility.description")} +

+
+
+ {APP_CONFIG.map((app) => { + const isVisible = visibleApps[app.id]; + // Disable button if this is the last visible app + const isDisabled = isVisible && visibleCount <= 1; + + return ( + handleToggle(app.id)} + icon={app.icon} + name={t(app.nameKey)} + > + {t(app.nameKey)} + + ); + })} +
+
+ ); +} + +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 ( + + ); +}