authorclover caruso <git@paperclover.net> 2026-10-16 00:08:15-07:00
committerclover caruso <git@paperclover.net> 2026-10-16 16:52:04-07:00
log0b3f74c4692000e2979902e327e147f623276230
tree956948ead2ac80d52939c0032e5ffa80bc9dba8d
parenta4d2ec0fc271b30cf89a4a5153c9b6cf44a986ca
signature Signed by SSH key SHA256:cOKiuRFOeSRxne6EWgHtdQQSlBxjOXm2hOCFnCdLQbQ (~clover)

feat: disable SnapShots in the fork

Clover does not want desktop SnapShots in this build. Hide capture settings from navigation and search, redirect the old settings URL, and remove the startup setup-resume redirect. Decode and persist capture enablement as false so previously enabled settings and native IPC updates cannot turn capture back on. Assisted-by: gpt-6.1-sol

7 files changed, 29 insertions(+), 40 deletions(-)

apps/web/src/components/settings/settingsNavigation.tsx+1-1
...@@ -56,7 +56,7 @@ const SETTINGS_NAV_ITEMS: ReadonlyArray<{...@@ -56,7 +56,7 @@ const SETTINGS_NAV_ITEMS: ReadonlyArray<{
56 to: SettingsPath;56 to: SettingsPath;
57 icon: ComponentType<{ className?: string }>;57 icon: ComponentType<{ className?: string }>;
58}> = (Object.keys(SETTINGS_SECTION_LABELS) as SettingsPath[])58}> = (Object.keys(SETTINGS_SECTION_LABELS) as SettingsPath[])
59 .filter((to) => to !== "/settings/diagnostics")59 .filter((to) => to !== "/settings/diagnostics" && to !== "/settings/snap-shot")
60 .map((to) => ({60 .map((to) => ({
61 to,61 to,
62 label: SETTINGS_SECTION_LABELS[to],62 label: SETTINGS_SECTION_LABELS[to],
apps/web/src/components/settings/settingsSearch.test.ts+8-19
...@@ -339,25 +339,14 @@ describe("searchSettings", () => {...@@ -339,25 +339,14 @@ describe("searchSettings", () => {
339 });339 });
340 });340 });
341341
342 it("routes conditional window capture settings to the stable toggle row", () => {342 it.each([
343 const targets = [343 "capture accessibility data",
344 "capture accessibility data",344 "capture shortcut",
345 "capture shortcut",345 "capture sound",
346 "capture sound",346 "capture flash",
347 "capture flash",347 "capture animations",
348 "capture animations",348 ])("hides disabled SnapShots settings for %s", (query) => {
349 ].map((query) => {349 expect(searchSettings(query).some((item) => item.to === "/settings/snap-shot")).toBe(false);
350 const match = searchSettings(query)[0];
351 return [match?.id, match?.targetId];
352 });
353
354 expect(targets).toEqual([
355 ["snap-shot-accessibility", "snap-shot-enabled"],
356 ["snap-shot-shortcut", "snap-shot-enabled"],
357 ["snap-shot-sound", "snap-shot-enabled"],
358 ["snap-shot-flash", "snap-shot-enabled"],
359 ["snap-shot-animations", "snap-shot-enabled"],
360 ]);
361 });350 });
362351
363 it("routes browser recording quality to integrations", () => {352 it("routes browser recording quality to integrations", () => {
apps/web/src/components/settings/settingsSearch.ts+2
...@@ -1153,6 +1153,7 @@ export function filterAvailableSettingsSearchItems(...@@ -1153,6 +1153,7 @@ export function filterAvailableSettingsSearchItems(
1153 const items: ReadonlyArray<SettingsSearchItem> = SETTINGS_SEARCH_ITEMS;1153 const items: ReadonlyArray<SettingsSearchItem> = SETTINGS_SEARCH_ITEMS;
1154 return items.filter(1154 return items.filter(
1155 (item) =>1155 (item) =>
1156 item.to !== "/settings/snap-shot" &&
1156 (!item.cloudOnly || availability.hasCloudPublicConfig) &&1157 (!item.cloudOnly || availability.hasCloudPublicConfig) &&
1157 (!item.environmentOnly || availability.hasEnvironment) &&1158 (!item.environmentOnly || availability.hasEnvironment) &&
1158 (!item.providerSettingsOnly || availability.hasProviderSettingsEnvironment) &&1159 (!item.providerSettingsOnly || availability.hasProviderSettingsEnvironment) &&
...@@ -1176,6 +1177,7 @@ export function searchSettings(...@@ -1176,6 +1177,7 @@ export function searchSettings(
11761177
1177 return items1178 return items
1178 .flatMap((item, index) => {1179 .flatMap((item, index) => {
1180 if (item.to === "/settings/snap-shot") return [];
1179 if (!isElectron && item.desktopOnly === true) return [];1181 if (!isElectron && item.desktopOnly === true) return [];
1180 if (item.releaseChannelOnly && !isElectron && HOSTED_APP_CHANNEL === null) return [];1182 if (item.releaseChannelOnly && !isElectron && HOSTED_APP_CHANNEL === null) return [];
1181 if (item.macOnly && !isMacPlatform(platform)) return [];1183 if (item.macOnly && !isMacPlatform(platform)) return [];
apps/web/src/routes/__root.tsx-11
...@@ -5,7 +5,6 @@ import { scopedProjectKey, scopeProjectRef } from "@t3tools/client-runtime/envir...@@ -5,7 +5,6 @@ import { scopedProjectKey, scopeProjectRef } from "@t3tools/client-runtime/envir
5import {5import {
6 Outlet,6 Outlet,
7 Link,7 Link,
8 redirect,
9 createRootRoute,8 createRootRoute,
10 type ErrorComponentProps,9 type ErrorComponentProps,
11 useLocation,10 useLocation,
...@@ -85,9 +84,7 @@ import {...@@ -85,9 +84,7 @@ import {
85 type KeybindingsUpdateToastController,84 type KeybindingsUpdateToastController,
86} from "../components/KeybindingsUpdateToast.logic";85} from "../components/KeybindingsUpdateToast.logic";
8786
88import { getDesktopSnapShotBridge } from "../lib/desktopSnapShot";
89import { installDesktopPasteAsText } from "../lib/desktopPasteAsText";87import { installDesktopPasteAsText } from "../lib/desktopPasteAsText";
90import { shouldResumeSnapShotSetupOnStartup } from "../lib/snapShotSetupResume";
9188
92export const Route = createRootRoute({89export const Route = createRootRoute({
93 beforeLoad: async ({ location }) => {90 beforeLoad: async ({ location }) => {
...@@ -108,14 +105,6 @@ export const Route = createRootRoute({...@@ -108,14 +105,6 @@ export const Route = createRootRoute({
108 }105 }
109106
110 const authGateState = await resolveInitialServerAuthGateState();107 const authGateState = await resolveInitialServerAuthGateState();
111 if (
112 authGateState.status === "authenticated" &&
113 getDesktopSnapShotBridge() &&
114 shouldResumeSnapShotSetupOnStartup() &&
115 location.pathname !== "/settings/snap-shot"
116 ) {
117 throw redirect({ to: "/settings/snap-shot", replace: true });
118 }
119 return {108 return {
120 authGateState,109 authGateState,
121 };110 };
apps/web/src/routes/settings.snap-shot.tsx+4-8
...@@ -1,11 +1,7 @@...@@ -1,11 +1,7 @@
1import { createFileRoute } from "@tanstack/react-router";1import { createFileRoute, redirect } from "@tanstack/react-router";
2
3import { SnapShotSettings } from "../components/settings/SnapShotSettings";
4
5function SettingsSnapShotRoute() {
6 return <SnapShotSettings />;
7}
82
9export const Route = createFileRoute("/settings/snap-shot")({3export const Route = createFileRoute("/settings/snap-shot")({
10 component: SettingsSnapShotRoute,4 beforeLoad: () => {
5 throw redirect({ to: "/settings/general", replace: true });
6 },
11});7});
packages/contracts/src/settings.test.ts+7
...@@ -8,6 +8,7 @@ import {...@@ -8,6 +8,7 @@ import {
8 ClientSettingsPatch,8 ClientSettingsPatch,
9 ClaudeSettings,9 ClaudeSettings,
10 DEFAULT_SERVER_SETTINGS,10 DEFAULT_SERVER_SETTINGS,
11 DEFAULT_CLIENT_SETTINGS,
11 requiredScopesForProjectMutation,12 requiredScopesForProjectMutation,
12 resolveProjectProviderInstanceEnabled,13 resolveProjectProviderInstanceEnabled,
13 resolveProviderInstanceEnabled,14 resolveProviderInstanceEnabled,
...@@ -473,6 +474,12 @@ describe("ClientSettings window capture", () => {...@@ -473,6 +474,12 @@ describe("ClientSettings window capture", () => {
473 });474 });
474 });475 });
475476
477 it("keeps SnapShots disabled when older settings enable them or a caller tries to persist them", () => {
478 expect(decodeClientSettings({ snapShotEnabled: true }).snapShotEnabled).toBe(false);
479 const saved = encodeClientSettings({ ...DEFAULT_CLIENT_SETTINGS, snapShotEnabled: true });
480 expect(saved.snapShotEnabled).toBe(false);
481 });
482
476 it("rejects unknown capture sounds", () => {483 it("rejects unknown capture sounds", () => {
477 expect(() => decodeClientSettingsPatch({ snapShotSound: "doorbell" })).toThrow();484 expect(() => decodeClientSettingsPatch({ snapShotSound: "doorbell" })).toThrow();
478 });485 });
packages/contracts/src/settings.ts+7-1
...@@ -491,7 +491,13 @@ export const ClientSettingsSchema = Schema.Struct({...@@ -491,7 +491,13 @@ export const ClientSettingsSchema = Schema.Struct({
491 timestampFormat: TimestampFormat.pipe(491 timestampFormat: TimestampFormat.pipe(
492 Schema.withDecodingDefault(Effect.succeed(DEFAULT_TIMESTAMP_FORMAT)),492 Schema.withDecodingDefault(Effect.succeed(DEFAULT_TIMESTAMP_FORMAT)),
493 ),493 ),
494 snapShotEnabled: Schema.Boolean.pipe(Schema.withDecodingDefault(Effect.succeed(false))),494 snapShotEnabled: Schema.Boolean.pipe(
495 Schema.decodeTo(
496 Schema.Boolean,
497 SchemaTransformation.transform({ decode: () => false, encode: () => false }),
498 ),
499 Schema.withDecodingDefault(Effect.succeed(false)),
500 ),
495 snapShotIncludeAccessibility: Schema.Boolean.pipe(501 snapShotIncludeAccessibility: Schema.Boolean.pipe(
496 Schema.withDecodingDefault(Effect.succeed(true)),502 Schema.withDecodingDefault(Effect.succeed(true)),
497 ),503 ),