mirror of
https://github.com/farion1231/cc-switch.git
synced 2026-07-28 00:35:32 +08:00
cfcf9452d0
* feat(window): add app-level window controls with settings toggle Add a persistent settings toggle to enable app-level minimize/maximize/close controls and hide system decorations when enabled, providing a Wayland-friendly fallback for broken native titlebar interactions. Co-authored-by: Cursor <cursoragent@cursor.com> * fix(window): restrict app-level window controls to Linux only and fix startup flicker - Guard useAppWindowControls with isLinux() in App.tsx so it's always false on macOS/Windows even if persisted as true - Wrap set_decorations call in lib.rs with #[cfg(target_os = "linux")] - Only show the toggle in WindowSettings on Linux - Skip setDecorations effect while settingsData is still loading to prevent the Rust-side decoration state from being overridden by the undefined->false fallback, which caused a brief title bar flicker --------- Co-authored-by: wzk <wx13571681304@outlook.com> Co-authored-by: Cursor <cursoragent@cursor.com> Co-authored-by: Jason <farion1231@gmail.com>
95 lines
3.5 KiB
TypeScript
95 lines
3.5 KiB
TypeScript
import { useTranslation } from "react-i18next";
|
|
import type { SettingsFormState } from "@/hooks/useSettings";
|
|
import { AppWindow, MonitorUp, Power, EyeOff } from "lucide-react";
|
|
import { ToggleRow } from "@/components/ui/toggle-row";
|
|
import { AnimatePresence, motion } from "framer-motion";
|
|
import { isLinux } from "@/lib/platform";
|
|
|
|
interface WindowSettingsProps {
|
|
settings: SettingsFormState;
|
|
onChange: (updates: Partial<SettingsFormState>) => void;
|
|
}
|
|
|
|
export function WindowSettings({ settings, onChange }: WindowSettingsProps) {
|
|
const { t } = useTranslation();
|
|
|
|
return (
|
|
<section className="space-y-4">
|
|
<div className="flex items-center gap-2 pb-2 border-b border-border/40">
|
|
<AppWindow className="h-4 w-4 text-primary" />
|
|
<h3 className="text-sm font-medium">{t("settings.windowBehavior")}</h3>
|
|
</div>
|
|
|
|
<div className="space-y-3">
|
|
<ToggleRow
|
|
icon={<Power className="h-4 w-4 text-orange-500" />}
|
|
title={t("settings.launchOnStartup")}
|
|
description={t("settings.launchOnStartupDescription")}
|
|
checked={!!settings.launchOnStartup}
|
|
onCheckedChange={(value) => onChange({ launchOnStartup: value })}
|
|
/>
|
|
|
|
<AnimatePresence initial={false}>
|
|
{settings.launchOnStartup && (
|
|
<motion.div
|
|
key="silent-startup"
|
|
initial={{ opacity: 0, y: 10 }}
|
|
animate={{ opacity: 1, y: 0 }}
|
|
exit={{ opacity: 0, y: 10 }}
|
|
transition={{ duration: 0.3 }}
|
|
>
|
|
<ToggleRow
|
|
icon={<EyeOff className="h-4 w-4 text-green-500" />}
|
|
title={t("settings.silentStartup")}
|
|
description={t("settings.silentStartupDescription")}
|
|
checked={!!settings.silentStartup}
|
|
onCheckedChange={(value) => onChange({ silentStartup: value })}
|
|
/>
|
|
</motion.div>
|
|
)}
|
|
</AnimatePresence>
|
|
|
|
<ToggleRow
|
|
icon={<MonitorUp className="h-4 w-4 text-purple-500" />}
|
|
title={t("settings.enableClaudePluginIntegration")}
|
|
description={t("settings.enableClaudePluginIntegrationDescription")}
|
|
checked={!!settings.enableClaudePluginIntegration}
|
|
onCheckedChange={(value) =>
|
|
onChange({ enableClaudePluginIntegration: value })
|
|
}
|
|
/>
|
|
|
|
<ToggleRow
|
|
icon={<MonitorUp className="h-4 w-4 text-cyan-500" />}
|
|
title={t("settings.skipClaudeOnboarding")}
|
|
description={t("settings.skipClaudeOnboardingDescription")}
|
|
checked={!!settings.skipClaudeOnboarding}
|
|
onCheckedChange={(value) => onChange({ skipClaudeOnboarding: value })}
|
|
/>
|
|
|
|
<ToggleRow
|
|
icon={<AppWindow className="h-4 w-4 text-blue-500" />}
|
|
title={t("settings.minimizeToTray")}
|
|
description={t("settings.minimizeToTrayDescription")}
|
|
checked={settings.minimizeToTrayOnClose}
|
|
onCheckedChange={(value) =>
|
|
onChange({ minimizeToTrayOnClose: value })
|
|
}
|
|
/>
|
|
|
|
{isLinux() && (
|
|
<ToggleRow
|
|
icon={<AppWindow className="h-4 w-4 text-amber-500" />}
|
|
title={t("settings.useAppWindowControls")}
|
|
description={t("settings.useAppWindowControlsDescription")}
|
|
checked={!!settings.useAppWindowControls}
|
|
onCheckedChange={(value) =>
|
|
onChange({ useAppWindowControls: value })
|
|
}
|
|
/>
|
|
)}
|
|
</div>
|
|
</section>
|
|
);
|
|
}
|