mirror of
https://github.com/alkimake/paperclip.git
synced 2026-06-14 01:50:39 +09:00
Replaces 12+ inline toggle button implementations across the app with a shared ToggleSwitch component that scales up on mobile for better touch targets. Default size is h-6/w-10 on mobile, h-5/w-9 on desktop; "lg" variant is h-7/w-12 on mobile, h-6/w-11 on desktop. Co-Authored-By: Paperclip <noreply@paperclip.ing>
113 lines
4.5 KiB
TypeScript
113 lines
4.5 KiB
TypeScript
import { useEffect, useState } from "react";
|
|
import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query";
|
|
import { FlaskConical } from "lucide-react";
|
|
import { instanceSettingsApi } from "@/api/instanceSettings";
|
|
import { useBreadcrumbs } from "../context/BreadcrumbContext";
|
|
import { queryKeys } from "../lib/queryKeys";
|
|
import { ToggleSwitch } from "@/components/ui/toggle-switch";
|
|
|
|
export function InstanceExperimentalSettings() {
|
|
const { setBreadcrumbs } = useBreadcrumbs();
|
|
const queryClient = useQueryClient();
|
|
const [actionError, setActionError] = useState<string | null>(null);
|
|
|
|
useEffect(() => {
|
|
setBreadcrumbs([
|
|
{ label: "Instance Settings" },
|
|
{ label: "Experimental" },
|
|
]);
|
|
}, [setBreadcrumbs]);
|
|
|
|
const experimentalQuery = useQuery({
|
|
queryKey: queryKeys.instance.experimentalSettings,
|
|
queryFn: () => instanceSettingsApi.getExperimental(),
|
|
});
|
|
|
|
const toggleMutation = useMutation({
|
|
mutationFn: async (patch: { enableIsolatedWorkspaces?: boolean; autoRestartDevServerWhenIdle?: boolean }) =>
|
|
instanceSettingsApi.updateExperimental(patch),
|
|
onSuccess: async () => {
|
|
setActionError(null);
|
|
await Promise.all([
|
|
queryClient.invalidateQueries({ queryKey: queryKeys.instance.experimentalSettings }),
|
|
queryClient.invalidateQueries({ queryKey: queryKeys.health }),
|
|
]);
|
|
},
|
|
onError: (error) => {
|
|
setActionError(error instanceof Error ? error.message : "Failed to update experimental settings.");
|
|
},
|
|
});
|
|
|
|
if (experimentalQuery.isLoading) {
|
|
return <div className="text-sm text-muted-foreground">Loading experimental settings...</div>;
|
|
}
|
|
|
|
if (experimentalQuery.error) {
|
|
return (
|
|
<div className="text-sm text-destructive">
|
|
{experimentalQuery.error instanceof Error
|
|
? experimentalQuery.error.message
|
|
: "Failed to load experimental settings."}
|
|
</div>
|
|
);
|
|
}
|
|
|
|
const enableIsolatedWorkspaces = experimentalQuery.data?.enableIsolatedWorkspaces === true;
|
|
const autoRestartDevServerWhenIdle = experimentalQuery.data?.autoRestartDevServerWhenIdle === true;
|
|
|
|
return (
|
|
<div className="max-w-4xl space-y-6">
|
|
<div className="space-y-2">
|
|
<div className="flex items-center gap-2">
|
|
<FlaskConical className="h-5 w-5 text-muted-foreground" />
|
|
<h1 className="text-lg font-semibold">Experimental</h1>
|
|
</div>
|
|
<p className="text-sm text-muted-foreground">
|
|
Opt into features that are still being evaluated before they become default behavior.
|
|
</p>
|
|
</div>
|
|
|
|
{actionError && (
|
|
<div className="rounded-md border border-destructive/40 bg-destructive/5 px-3 py-2 text-sm text-destructive">
|
|
{actionError}
|
|
</div>
|
|
)}
|
|
|
|
<section className="rounded-xl border border-border bg-card p-5">
|
|
<div className="flex items-start justify-between gap-4">
|
|
<div className="space-y-1.5">
|
|
<h2 className="text-sm font-semibold">Enable Isolated Workspaces</h2>
|
|
<p className="max-w-2xl text-sm text-muted-foreground">
|
|
Show execution workspace controls in project configuration and allow isolated workspace behavior for new
|
|
and existing issue runs.
|
|
</p>
|
|
</div>
|
|
<ToggleSwitch
|
|
checked={enableIsolatedWorkspaces}
|
|
onCheckedChange={() => toggleMutation.mutate({ enableIsolatedWorkspaces: !enableIsolatedWorkspaces })}
|
|
disabled={toggleMutation.isPending}
|
|
aria-label="Toggle isolated workspaces experimental setting"
|
|
/>
|
|
</div>
|
|
</section>
|
|
|
|
<section className="rounded-xl border border-border bg-card p-5">
|
|
<div className="flex items-start justify-between gap-4">
|
|
<div className="space-y-1.5">
|
|
<h2 className="text-sm font-semibold">Auto-Restart Dev Server When Idle</h2>
|
|
<p className="max-w-2xl text-sm text-muted-foreground">
|
|
In `pnpm dev:once`, wait for all queued and running local agent runs to finish, then restart the server
|
|
automatically when backend changes or migrations make the current boot stale.
|
|
</p>
|
|
</div>
|
|
<ToggleSwitch
|
|
checked={autoRestartDevServerWhenIdle}
|
|
onCheckedChange={() => toggleMutation.mutate({ autoRestartDevServerWhenIdle: !autoRestartDevServerWhenIdle })}
|
|
disabled={toggleMutation.isPending}
|
|
aria-label="Toggle guarded dev-server auto-restart"
|
|
/>
|
|
</div>
|
|
</section>
|
|
</div>
|
|
);
|
|
}
|