From 0918451e02995181c42f188adecb072d771f6a3f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Bombeck?= Date: Thu, 22 Oct 2026 00:09:40 +0200 Subject: [PATCH] fix(settings): unlist Preview features until the topic pages ship The switch was stored and shown, but nothing reads the topics flag yet, so the page promised a change it could not make. The section, its nav entry, its loader and its copy are gone, so its palette entry goes with them; /settings/preview is no longer a route. The stored flag, /api/settings/preview-features and its backup round-trip stay, and the column's pending-consumer note says why. --- e2e/settings-admin-one-piece.spec.ts | 1 - messages/de.json | 15 --- messages/en.json | 15 --- messages/es.json | 15 --- messages/fr.json | 15 --- messages/it.json | 15 --- messages/ko.json | 15 --- messages/nl.json | 15 --- messages/pl.json | 15 --- prisma/schema.prisma | 6 +- src/__tests__/settings-copy-tense.test.ts | 12 +- src/__tests__/settings-legacy-routes.test.ts | 5 +- .../__tests__/preview-section.test.tsx | 51 -------- .../__tests__/settings-shell.test.tsx | 12 +- src/components/settings/preview-section.tsx | 116 ------------------ src/components/settings/section-slugs.ts | 7 +- .../settings/settings-section-loader.tsx | 5 - src/components/settings/settings-shell.tsx | 7 -- src/lib/query-keys/settings.ts | 3 - src/lib/record-settings/classification.ts | 1 - src/lib/settings/preview-features.ts | 4 +- 21 files changed, 23 insertions(+), 327 deletions(-) delete mode 100644 src/components/settings/__tests__/preview-section.test.tsx delete mode 100644 src/components/settings/preview-section.tsx diff --git a/e2e/settings-admin-one-piece.spec.ts b/e2e/settings-admin-one-piece.spec.ts index 3f10f6540..2b8e70726 100644 --- a/e2e/settings-admin-one-piece.spec.ts +++ b/e2e/settings-admin-one-piece.spec.ts @@ -58,7 +58,6 @@ const SETTINGS_ROUTES = [ "/settings/api", "/settings/mcp", "/settings/advanced", - "/settings/preview", "/settings/about", ] as const; diff --git a/messages/de.json b/messages/de.json index f2480fafb..d78afea07 100644 --- a/messages/de.json +++ b/messages/de.json @@ -6141,10 +6141,6 @@ "access": { "title": "Geteilter Zugriff", "subtitle": "Wer deine Gesundheitsakte öffnen kann und wessen Akte du öffnen kannst." - }, - "preview": { - "title": "Vorschau-Funktionen", - "subtitle": "Probier aus, was noch nicht fertig ist. Alles hier bleibt aus, bis du es einschaltest." } }, "profile": "Profil", @@ -7628,17 +7624,6 @@ "passkeyRemovedToast": "Passkey entfernt.", "integrationDisconnected": "{provider} getrennt.", "integrationDisconnectFailed": "{provider} konnte nicht getrennt werden.", - "preview": { - "topics": { - "title": "Themen (Beta)", - "description": "Fügt einen eigenen Eintrag Themen hinzu, sobald die Übersichtsseiten über den einzelnen Insights-Seiten fertig sind.", - "detail": "Deine Insights-Seiten, die Navigation und alle Links bleiben genau wie sie sind. Die Themenseiten kommen mit einem späteren Update; dieser Schalter legt fest, ob du sie siehst.", - "savedOn": "Themen-Vorschau eingeschaltet.", - "savedOff": "Themen-Vorschau ausgeschaltet." - }, - "loadError": "Deine Vorschau-Einstellungen konnten nicht geladen werden.", - "feedbackLink": "Feedback in den GitHub-Diskussionen geben" - }, "timezoneSaved": "Zeitzone gespeichert.", "moduleState": { "on": "An", diff --git a/messages/en.json b/messages/en.json index 4cdf487f5..10a8e34e6 100644 --- a/messages/en.json +++ b/messages/en.json @@ -6141,10 +6141,6 @@ "access": { "title": "Shared access", "subtitle": "Who can open your health record, and whose you can open." - }, - "preview": { - "title": "Preview features", - "subtitle": "Try what is not finished yet. Everything here stays off until you switch it on." } }, "profile": "Profile", @@ -7628,17 +7624,6 @@ "passkeyRemovedToast": "Passkey removed.", "integrationDisconnected": "{provider} disconnected.", "integrationDisconnectFailed": "Could not disconnect {provider}.", - "preview": { - "topics": { - "title": "Topics (beta)", - "description": "Will add a separate Topics entry with overview pages above the single-metric Insights pages once they are ready.", - "detail": "Your Insights pages, navigation and links stay exactly as they are. The topic pages arrive in a later update; this switch decides whether you see them.", - "savedOn": "Topics preview switched on.", - "savedOff": "Topics preview switched off." - }, - "loadError": "Could not load your preview settings.", - "feedbackLink": "Share feedback in the GitHub discussions" - }, "timezoneSaved": "Timezone saved.", "moduleState": { "on": "On", diff --git a/messages/es.json b/messages/es.json index 8d7873a7c..e331d5c2a 100644 --- a/messages/es.json +++ b/messages/es.json @@ -6141,10 +6141,6 @@ "access": { "title": "Acceso compartido", "subtitle": "Quién puede abrir tu historial de salud y cuál puedes abrir tú." - }, - "preview": { - "title": "Funciones en vista previa", - "subtitle": "Prueba lo que aún no está terminado. Todo aquí sigue desactivado hasta que lo actives." } }, "profile": "Perfil", @@ -7628,17 +7624,6 @@ "passkeyRemovedToast": "Passkey eliminada.", "integrationDisconnected": "{provider} desconectado.", "integrationDisconnectFailed": "No se pudo desconectar {provider}.", - "preview": { - "topics": { - "title": "Temas (beta)", - "description": "Añadirá una entrada aparte, Temas, con páginas de resumen por encima de las páginas de cada métrica cuando estén listas.", - "detail": "Tus páginas de análisis, la navegación y los enlaces se quedan exactamente como están. Las páginas de temas llegan en una actualización posterior; este interruptor decide si las ves.", - "savedOn": "Vista previa de Temas activada.", - "savedOff": "Vista previa de Temas desactivada." - }, - "loadError": "No se pudieron cargar tus ajustes de vista previa.", - "feedbackLink": "Comparte tu opinión en las discusiones de GitHub" - }, "timezoneSaved": "Zona horaria guardada.", "moduleState": { "on": "Activado", diff --git a/messages/fr.json b/messages/fr.json index a689b23bc..e4ca44d21 100644 --- a/messages/fr.json +++ b/messages/fr.json @@ -6141,10 +6141,6 @@ "access": { "title": "Accès partagé", "subtitle": "Qui peut ouvrir votre dossier de santé, et lequel vous pouvez ouvrir." - }, - "preview": { - "title": "Fonctions en aperçu", - "subtitle": "Essayez ce qui n’est pas encore terminé. Tout reste désactivé ici tant que vous ne l’activez pas." } }, "profile": "Profil", @@ -7628,17 +7624,6 @@ "passkeyRemovedToast": "Passkey supprimée.", "integrationDisconnected": "{provider} déconnecté.", "integrationDisconnectFailed": "Impossible de déconnecter {provider}.", - "preview": { - "topics": { - "title": "Thèmes (bêta)", - "description": "Ajoutera une entrée Thèmes distincte, avec des pages de synthèse au-dessus des pages par mesure, dès qu'elles seront prêtes.", - "detail": "Vos pages d’analyse, la navigation et les liens restent exactement tels quels. Les pages de thèmes arrivent dans une mise à jour ultérieure ; cet interrupteur décide si vous les voyez.", - "savedOn": "Aperçu des thèmes activé.", - "savedOff": "Aperçu des thèmes désactivé." - }, - "loadError": "Impossible de charger vos réglages d’aperçu.", - "feedbackLink": "Donner votre avis dans les discussions GitHub" - }, "timezoneSaved": "Fuseau horaire enregistré.", "moduleState": { "on": "Activé", diff --git a/messages/it.json b/messages/it.json index 276cfd2c3..6af2d8b19 100644 --- a/messages/it.json +++ b/messages/it.json @@ -6141,10 +6141,6 @@ "access": { "title": "Accesso condiviso", "subtitle": "Chi può aprire la tua cartella sanitaria e quale puoi aprire tu." - }, - "preview": { - "title": "Funzioni in anteprima", - "subtitle": "Prova ciò che non è ancora finito. Qui tutto resta spento finché non lo attivi." } }, "profile": "Profilo", @@ -7628,17 +7624,6 @@ "passkeyRemovedToast": "Passkey rimossa.", "integrationDisconnected": "{provider} disconnesso.", "integrationDisconnectFailed": "Impossibile disconnettere {provider}.", - "preview": { - "topics": { - "title": "Temi (beta)", - "description": "Aggiungerà una voce Temi separata, con pagine di panoramica sopra le pagine delle singole metriche, appena saranno pronte.", - "detail": "Le pagine delle analisi, la navigazione e i link restano esattamente come sono. Le pagine dei temi arrivano con un aggiornamento successivo; questo interruttore decide se le vedi.", - "savedOn": "Anteprima dei temi attivata.", - "savedOff": "Anteprima dei temi disattivata." - }, - "loadError": "Impossibile caricare le impostazioni di anteprima.", - "feedbackLink": "Lascia un parere nelle discussioni su GitHub" - }, "timezoneSaved": "Fuso orario salvato.", "moduleState": { "on": "Attivo", diff --git a/messages/ko.json b/messages/ko.json index de47beccd..665971476 100644 --- a/messages/ko.json +++ b/messages/ko.json @@ -6141,10 +6141,6 @@ "access": { "title": "공유 접근", "subtitle": "내 건강 기록을 누가 열 수 있고, 내가 누구의 기록을 열 수 있는지예요." - }, - "preview": { - "title": "미리 보기 기능", - "subtitle": "아직 완성되지 않은 기능을 써 보세요. 직접 켜기 전까지는 모두 꺼져 있습니다." } }, "profile": "프로필", @@ -7628,17 +7624,6 @@ "passkeyRemovedToast": "패스키를 삭제했어요.", "integrationDisconnected": "{provider} 연결을 해제했어요.", "integrationDisconnectFailed": "{provider} 연결을 해제하지 못했어요.", - "preview": { - "topics": { - "title": "주제 (베타)", - "description": "준비되면 개별 지표 페이지 위에 개요 페이지가 있는 별도의 주제 항목을 추가해요.", - "detail": "인사이트 페이지, 메뉴, 링크는 지금 그대로 유지됩니다. 주제 페이지는 이후 업데이트에서 제공되며, 이 스위치로 표시 여부를 정합니다.", - "savedOn": "주제 미리 보기를 켰습니다.", - "savedOff": "주제 미리 보기를 껐습니다." - }, - "loadError": "미리 보기 설정을 불러오지 못했습니다.", - "feedbackLink": "GitHub 토론에서 의견 남기기" - }, "timezoneSaved": "시간대를 저장했습니다.", "moduleState": { "on": "켜짐", diff --git a/messages/nl.json b/messages/nl.json index 7b94c1ea4..ab1552351 100644 --- a/messages/nl.json +++ b/messages/nl.json @@ -6141,10 +6141,6 @@ "access": { "title": "Gedeelde toegang", "subtitle": "Wie je gezondheidsdossier kan openen, en wiens dossier jij kunt openen." - }, - "preview": { - "title": "Previewfuncties", - "subtitle": "Probeer wat nog niet af is. Alles hier blijft uit tot je het aanzet." } }, "profile": "Profiel", @@ -7628,17 +7624,6 @@ "passkeyRemovedToast": "Passkey verwijderd.", "integrationDisconnected": "{provider} ontkoppeld.", "integrationDisconnectFailed": "{provider} kon niet worden ontkoppeld.", - "preview": { - "topics": { - "title": "Onderwerpen (bèta)", - "description": "Voegt een apart item Onderwerpen toe, met overzichtspagina’s boven de pagina’s per meting, zodra die klaar zijn.", - "detail": "Je inzichtpagina’s, navigatie en links blijven precies zoals ze zijn. De onderwerppagina’s komen met een latere update; deze schakelaar bepaalt of je ze ziet.", - "savedOn": "Preview van onderwerpen ingeschakeld.", - "savedOff": "Preview van onderwerpen uitgeschakeld." - }, - "loadError": "Je preview-instellingen konden niet worden geladen.", - "feedbackLink": "Geef feedback in de GitHub-discussies" - }, "timezoneSaved": "Tijdzone opgeslagen.", "moduleState": { "on": "Aan", diff --git a/messages/pl.json b/messages/pl.json index 7fc928cd2..35fe5b2ca 100644 --- a/messages/pl.json +++ b/messages/pl.json @@ -6141,10 +6141,6 @@ "access": { "title": "Udostępniony dostęp", "subtitle": "Kto może otworzyć twoją kartę zdrowia i czyją kartę możesz otworzyć ty." - }, - "preview": { - "title": "Funkcje w podglądzie", - "subtitle": "Wypróbuj to, co nie jest jeszcze gotowe. Wszystko tutaj pozostaje wyłączone, dopóki tego nie włączysz." } }, "profile": "Profil", @@ -7628,17 +7624,6 @@ "passkeyRemovedToast": "Usunięto passkey.", "integrationDisconnected": "Rozłączono {provider}.", "integrationDisconnectFailed": "Nie udało się rozłączyć {provider}.", - "preview": { - "topics": { - "title": "Tematy (beta)", - "description": "Doda osobną pozycję Tematy ze stronami przeglądowymi nad stronami poszczególnych pomiarów, gdy będą gotowe.", - "detail": "Strony analiz, nawigacja i linki pozostają dokładnie takie, jakie są. Strony tematów pojawią się w późniejszej aktualizacji; ten przełącznik decyduje, czy je zobaczysz.", - "savedOn": "Podgląd tematów włączony.", - "savedOff": "Podgląd tematów wyłączony." - }, - "loadError": "Nie udało się wczytać ustawień podglądu.", - "feedbackLink": "Podziel się opinią w dyskusjach na GitHubie" - }, "timezoneSaved": "Strefa czasowa zapisana.", "moduleState": { "on": "Włączone", diff --git a/prisma/schema.prisma b/prisma/schema.prisma index cf97a4241..860778e7a 100644 --- a/prisma/schema.prisma +++ b/prisma/schema.prisma @@ -388,9 +388,9 @@ model User { // Shape: { "version": 1, "labs": { "view": "list", "order": [""], "sortDir": "manual" }, ... } moduleListLayoutJson Json? @map("module_list_layout_json") /// Per-user opt-in to preview features, one boolean per flag, all off by - /// default (`src/lib/settings/preview-features.ts`). Read and written by - /// Settings > System through `/api/settings/preview-features`. - /// @pending-consumer(topics preview) the `topics` flag is stored and shown, but no surface reads it yet; the topic overview pages will. + /// default (`src/lib/settings/preview-features.ts`). Read and written + /// through `/api/settings/preview-features` and carried by the backup. + /// @pending-consumer(topics preview) the `topics` flag is stored, but no surface reads it and the Settings > System switch is unlisted until the topic overview pages ship. previewFeaturesJson Json? @map("preview_features_json") /// Optional activity goals the person set for themselves: workouts, active /// minutes and steps per week, steps per month. Null or an absent key = no diff --git a/src/__tests__/settings-copy-tense.test.ts b/src/__tests__/settings-copy-tense.test.ts index 31d44ea71..f6298b988 100644 --- a/src/__tests__/settings-copy-tense.test.ts +++ b/src/__tests__/settings-copy-tense.test.ts @@ -1,11 +1,10 @@ /** * Copy that promises something not yet shipped says so. * - * The Topics preview switch exists before its pages do, so its description is - * in the future tense in every locale's source (English) and in German; and - * the workout-route switch is off for new accounts, which is what its detail + * The workout-route switch is off for new accounts, which is what its detail * says rather than "off by default": an account that already held tracks at - * the upgrade started with it on (migration 0434). + * the upgrade started with it on (migration 0434). (The Topics preview switch + * this file also held is unlisted until its pages ship, and its copy with it.) */ import { describe, expect, it } from "vitest"; @@ -13,11 +12,6 @@ import en from "../../messages/en.json"; import de from "../../messages/de.json"; describe("settings copy tense", () => { - it("describes the Topics preview as something it will add", () => { - expect(en.settings.preview.topics.description).toMatch(/^Will add /); - expect(de.settings.preview.topics.description).toMatch(/sobald/); - }); - it("says workout routes are off for new accounts", () => { expect(en.settings.privacy.workoutRoutes.detail).toMatch( /^Off for new accounts\./, diff --git a/src/__tests__/settings-legacy-routes.test.ts b/src/__tests__/settings-legacy-routes.test.ts index db699d3bc..c04cbe5ad 100644 --- a/src/__tests__/settings-legacy-routes.test.ts +++ b/src/__tests__/settings-legacy-routes.test.ts @@ -146,10 +146,7 @@ describe("historical Settings addresses", () => { // one silently. Module pages are new in v1.44 and are allowed here. const listed = new Set(HISTORICAL_SETTINGS_PATHS); const unlisted = routable.filter( - (path) => - !listed.has(path) && - !path.startsWith("/settings/modules/") && - path !== "/settings/preview", + (path) => !listed.has(path) && !path.startsWith("/settings/modules/"), ); expect(unlisted).toEqual([]); }); diff --git a/src/components/settings/__tests__/preview-section.test.tsx b/src/components/settings/__tests__/preview-section.test.tsx deleted file mode 100644 index 7dc3e11ba..000000000 --- a/src/components/settings/__tests__/preview-section.test.tsx +++ /dev/null @@ -1,51 +0,0 @@ -import { describe, expect, it } from "vitest"; -import { renderToStaticMarkup } from "react-dom/server"; -import { QueryClient, QueryClientProvider } from "@tanstack/react-query"; - -import { I18nProvider } from "@/lib/i18n/context"; -import { queryKeys } from "@/lib/query-keys"; -import { PreviewSection } from "../preview-section"; -import { primeLocales } from "@/__tests__/helpers/prime-locales"; - -primeLocales("de"); - -function render(topics: boolean | undefined, locale: "en" | "de" = "en") { - const client = new QueryClient({ - defaultOptions: { queries: { retry: false, refetchOnMount: false } }, - }); - if (topics !== undefined) { - client.setQueryData(queryKeys.previewFeatures(), { topics }); - } - return renderToStaticMarkup( - - - - - , - ); -} - -describe("", () => { - it("shows the Topics switch off by default, saved on change", () => { - const html = render(false); - expect(html).toContain('data-slot="settings-preview-topics-switch"'); - expect(html).toMatch( - /data-slot="settings-preview-topics-switch"[^>]*aria-checked="false"|aria-checked="false"[^>]*data-slot="settings-preview-topics-switch"/, - ); - expect(html).toContain("Topics (beta)"); - // A switch, no Save: one save model per card. - expect(html).not.toContain('type="submit"'); - }); - - it("reads on once the person switched it on", () => { - expect(render(true)).toMatch( - /data-slot="settings-preview-topics-switch"[^>]*aria-checked="true"|aria-checked="true"[^>]*data-slot="settings-preview-topics-switch"/, - ); - }); - - it("says the existing pages stay as they are and nothing raw leaks", () => { - const html = render(false, "de"); - expect(html).toContain("Themen (Beta)"); - expect(html).not.toContain("settings.preview."); - }); -}); diff --git a/src/components/settings/__tests__/settings-shell.test.tsx b/src/components/settings/__tests__/settings-shell.test.tsx index dfeed9e79..117aa294f 100644 --- a/src/components/settings/__tests__/settings-shell.test.tsx +++ b/src/components/settings/__tests__/settings-shell.test.tsx @@ -170,12 +170,19 @@ describe("SETTINGS_SECTION_SLUGS", () => { // v1.23 — "Data & Privacy" assembles the export / deletion / retention / // encryption / session / activity pieces into one pane, after `advanced`. "privacy", - // v1.44 — per-user preview opt-ins, in the System group before About. - "preview", "about", ]); }); + it("lists no Preview features page until the topic pages ship", () => { + // The stored flag and its API stay; the page and its nav entry return + // with the first preview the switch actually turns on. + expect(isSettingsSectionSlug("preview")).toBe(false); + expect(SETTINGS_SECTIONS.some((s) => s.slug === ("preview" as never))).toBe( + false, + ); + }); + it("`isSettingsSectionSlug` accepts known slugs and rejects others", () => { for (const slug of SETTINGS_SECTION_SLUGS) { expect(isSettingsSectionSlug(slug)).toBe(true); @@ -242,7 +249,6 @@ describe("", () => { gesundheitsakte: "data", privacy: "data", advanced: "data", - preview: "system", about: "system", }); // Every routable section has a nav entry, and nothing else does. diff --git a/src/components/settings/preview-section.tsx b/src/components/settings/preview-section.tsx deleted file mode 100644 index 9df4789e5..000000000 --- a/src/components/settings/preview-section.tsx +++ /dev/null @@ -1,116 +0,0 @@ -"use client"; - -/** - * Settings > System > Preview features. - * - * One switch per preview feature, each off until the person turns it on, each - * saved the moment it changes (`PATCH /api/settings/preview-features`). A - * preview adds something beside what is there and never replaces a page. - * - * The `topics` flag is stored and shown here; the topic overview pages that - * read it arrive in a later release, and the card says so rather than - * promising a change the switch does not make yet. - */ - -import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query"; -import Link from "next/link"; -import { LayoutDashboard } from "lucide-react"; - -import { toastWrittenOutcome } from "@/components/outcome/outcome-toast"; -import { SettingsCard } from "@/components/settings/settings-card"; -import { SettingsCardHeader } from "@/components/settings/_card-header"; -import { InlineAction } from "@/components/ui/inline-action"; -import { QueryErrorRow } from "@/components/ui/query-error-row"; -import { Switch } from "@/components/ui/switch"; -import { apiGet, apiPatch } from "@/lib/api/api-fetch"; -import { showErrorToast } from "@/lib/errors/error-toast"; -import { useTranslations } from "@/lib/i18n/context"; -import { queryKeys } from "@/lib/query-keys"; -import { - DEFAULT_PREVIEW_FEATURES, - type PreviewFeatures, -} from "@/lib/settings/preview-features"; - -const DISCUSSIONS_URL = "https://github.com/MBombeck/HealthLog/discussions"; - -export function PreviewSection() { - const { t } = useTranslations(); - const queryClient = useQueryClient(); - const key = queryKeys.previewFeatures(); - - const query = useQuery({ - queryKey: key, - queryFn: () => apiGet("/api/settings/preview-features"), - }); - const features = query.data ?? DEFAULT_PREVIEW_FEATURES; - - const toggle = useMutation({ - mutationKey: key, - mutationFn: (topics: boolean) => - apiPatch("/api/settings/preview-features", { topics }), - onMutate: async (topics) => { - await queryClient.cancelQueries({ queryKey: key }); - const previous = queryClient.getQueryData(key); - queryClient.setQueryData(key, { - ...(previous ?? DEFAULT_PREVIEW_FEATURES), - topics, - }); - return { previous }; - }, - onSuccess: (saved, topics) => { - if (saved) queryClient.setQueryData(key, saved); - toastWrittenOutcome( - "success", - topics - ? t("settings.preview.topics.savedOn") - : t("settings.preview.topics.savedOff"), - ); - }, - onError: (failure, _topics, context) => { - queryClient.setQueryData(key, context?.previous); - showErrorToast(t("settings.savingError"), { cause: failure }); - }, - }); - - return ( - - toggle.mutate(next)} - aria-labelledby="settings-preview-topics-title" - /> - } - /> - {query.isError ? ( - void query.refetch()} - /> - ) : null} -

{t("settings.preview.topics.detail")}

-

- - - {t("settings.preview.feedbackLink")} - - -

-
- ); -} diff --git a/src/components/settings/section-slugs.ts b/src/components/settings/section-slugs.ts index 89d05e243..b6f69ed40 100644 --- a/src/components/settings/section-slugs.ts +++ b/src/components/settings/section-slugs.ts @@ -114,9 +114,10 @@ export const SETTINGS_SECTION_SLUGS = [ // pieces into one coherent privacy pane. Sits next to `advanced` (the // destructive-action home) and before `about`. "privacy", - // v1.44 — "Preview features": per-user opt-in to things finished enough to - // try and not yet the default. Sits in the System group before About. - "preview", + // v1.44 — "Preview features" (per-user opt-ins, Settings > System) is not + // listed until the first preview it switches, the topic pages, ships: a + // switch that changes nothing is a promise the page cannot keep. The stored + // flag, `/api/settings/preview-features` and its backup round-trip stay. "about", ] as const; diff --git a/src/components/settings/settings-section-loader.tsx b/src/components/settings/settings-section-loader.tsx index 252c75905..41aecb597 100644 --- a/src/components/settings/settings-section-loader.tsx +++ b/src/components/settings/settings-section-loader.tsx @@ -124,10 +124,6 @@ const LOADERS: Record< import("@/components/settings/privacy-section").then( (m) => m.PrivacySection, ), - preview: () => - import("@/components/settings/preview-section").then( - (m) => m.PreviewSection, - ), }; const SECTIONS: Record> = { @@ -162,7 +158,6 @@ const SECTIONS: Record> = { export: dynamic(LOADERS.export, { loading: () => }), advanced: dynamic(LOADERS.advanced, { loading: () => }), privacy: dynamic(LOADERS.privacy, { loading: () => }), - preview: dynamic(LOADERS.preview, { loading: () => }), }; /** diff --git a/src/components/settings/settings-shell.tsx b/src/components/settings/settings-shell.tsx index b260fa6d6..29c8b1af2 100644 --- a/src/components/settings/settings-shell.tsx +++ b/src/components/settings/settings-shell.tsx @@ -26,7 +26,6 @@ import { CloudSun, Download, FileHeart, - FlaskConical, Gauge, Info, KeyRound, @@ -275,12 +274,6 @@ export const SETTINGS_SECTIONS: readonly SettingsSection[] = [ group: "data", }, // ── System ── - { - slug: "preview", - titleKey: "settings.sections.preview.title", - icon: FlaskConical, - group: "system", - }, { slug: "about", titleKey: "settings.sections.about.title", diff --git a/src/lib/query-keys/settings.ts b/src/lib/query-keys/settings.ts index 95c1a4f13..03673daa1 100644 --- a/src/lib/query-keys/settings.ts +++ b/src/lib/query-keys/settings.ts @@ -44,9 +44,6 @@ export const settingsKeys = { */ moduleListLayout: () => ["settings", "module-list-layout"] as const, - /** The per-user preview-feature opt-ins behind `/api/settings/preview-features`. */ - previewFeatures: () => ["settings", "preview-features"] as const, - /** * v1.35.0 — which pillars count toward the Health Score, behind * `GET/PATCH /api/auth/me/health-score-config`. Its own cell rather than diff --git a/src/lib/record-settings/classification.ts b/src/lib/record-settings/classification.ts index 8d54e3eb1..fbeda64b2 100644 --- a/src/lib/record-settings/classification.ts +++ b/src/lib/record-settings/classification.ts @@ -98,7 +98,6 @@ export const SETTINGS_DESTINATION_INVENTORY = { export: PERSONAL, advanced: PERSONAL, privacy: PERSONAL, - preview: PERSONAL, about: PERSONAL, } as const satisfies Record< SettingsSectionSlug, diff --git a/src/lib/settings/preview-features.ts b/src/lib/settings/preview-features.ts index cd184520d..514b55fd1 100644 --- a/src/lib/settings/preview-features.ts +++ b/src/lib/settings/preview-features.ts @@ -7,7 +7,9 @@ * * Flags: * - `topics`: topic overview pages above the single-metric Insights pages. - * Stored and shown in Settings > System; no surface reads it yet. + * Stored, served by `/api/settings/preview-features` and carried by the + * backup. The Settings > System switch is not listed until the topic pages + * ship, because nothing reads the flag yet. * * Unknown keys in a stored blob are dropped on read, so a flag retired later * disappears cleanly and a malformed blob reads as everything off.