| author | |
| committer | |
| log | 115640ae49924c9e4e6215bd8d911445ad932bff |
| tree | 320b02c82b07949c2513c83c0372f779a7461ade |
| parent | 3b44698d07c722471279d6a933499d6108148632 |
| signature | Signed by PGP key B5690EEEBB952194 |
Co-authored-by: Claude Opus 5.5 (1M context) <noreply@anthropic.com>4 files changed, 37 insertions(+), 1 deletions(-)
apps/web/src/components/onboarding/WelcomeWizard.tsx+16-1| ... | @@ -35,6 +35,7 @@ import { useCallback, useEffect, useMemo, useRef, useState } from "react"; | ... | @@ -35,6 +35,7 @@ import { useCallback, useEffect, useMemo, useRef, useState } from "react"; |
| 35 | import { TYPOGRAPHY_ADVANCED_STORAGE_KEY } from "../../appearanceFonts"; | 35 | import { TYPOGRAPHY_ADVANCED_STORAGE_KEY } from "../../appearanceFonts"; |
| 36 | import { useLocalStorage } from "../../hooks/useLocalStorage"; | 36 | import { useLocalStorage } from "../../hooks/useLocalStorage"; |
| 37 | import { hasCloudPublicConfig } from "../../cloud/publicConfig"; | 37 | import { hasCloudPublicConfig } from "../../cloud/publicConfig"; |
| 38 | import { PRIVACY_POLICY_URL } from "../../legalLinks"; | ||
| 38 | import { useT3ConnectAuthPrompt } from "../clerk/useT3ConnectAuthPrompt"; | 39 | import { useT3ConnectAuthPrompt } from "../clerk/useT3ConnectAuthPrompt"; |
| 39 | import { useCompleteOnboarding } from "../../onboarding/firstRun"; | 40 | import { useCompleteOnboarding } from "../../onboarding/firstRun"; |
| 40 | import { | 41 | import { |
| ... | @@ -413,8 +414,22 @@ function ConnectionStep({ | ... | @@ -413,8 +414,22 @@ function ConnectionStep({ |
| 413 | </Collapsible> | 414 | </Collapsible> |
| 414 | </div> | 415 | </div> |
| 415 | </div> | 416 | </div> |
| 416 | <div className="mt-6 flex items-center justify-end gap-3"> | 417 | <div className="mt-6 flex flex-col-reverse gap-4 sm:flex-row sm:items-center sm:justify-between sm:gap-6"> |
| 418 | <p className="min-w-0 text-xs leading-relaxed text-muted-foreground"> | ||
| 419 | T3 Code collects anonymous usage data to help us improve it. To read more about how your | ||
| 420 | data is used and how to opt out, see our{" "} | ||
| 421 | <a | ||
| 422 | className="underline underline-offset-2 hover:text-foreground" | ||
| 423 | href={PRIVACY_POLICY_URL} | ||
| 424 | target="_blank" | ||
| 425 | rel="noreferrer noopener" | ||
| 426 | > | ||
| 427 | privacy policy | ||
| 428 | </a> | ||
| 429 | . | ||
| 430 | </p> | ||
| 417 | <Button | 431 | <Button |
| 432 | className="shrink-0 self-end" | ||
| 418 | ref={continueRef} | 433 | ref={continueRef} |
| 419 | autoFocus={!expandPairingInitially} | 434 | autoFocus={!expandPairingInitially} |
| 420 | disabled={!ready || isPairing} | 435 | disabled={!ready || isPairing} |
apps/web/src/components/settings/SettingsPanels.tsx+14| ... | @@ -1,6 +1,7 @@ | ... | @@ -1,6 +1,7 @@ |
| 1 | import { SettingsGroup } from "./SettingsGroup"; | 1 | import { SettingsGroup } from "./SettingsGroup"; |
| 2 | import { Spinner } from "~/components/ui/spinner"; | 2 | import { Spinner } from "~/components/ui/spinner"; |
| 3 | import { NotificationSettings } from "./NotificationSettings"; | 3 | import { NotificationSettings } from "./NotificationSettings"; |
| 4 | import { PRIVACY_POLICY_URL } from "../../legalLinks"; | ||
| 4 | import { ArchiveIcon, ArchiveX, CheckIcon, ChevronRightIcon, SettingsIcon } from "lucide-react"; | 5 | import { ArchiveIcon, ArchiveX, CheckIcon, ChevronRightIcon, SettingsIcon } from "lucide-react"; |
| 5 | import { Link, useNavigate } from "@tanstack/react-router"; | 6 | import { Link, useNavigate } from "@tanstack/react-router"; |
| 6 | import type { CSSProperties, ReactNode } from "react"; | 7 | import type { CSSProperties, ReactNode } from "react"; |
| ... | @@ -3342,6 +3343,19 @@ export function GeneralSettingsPanel() { | ... | @@ -3342,6 +3343,19 @@ export function GeneralSettingsPanel() { |
| 3342 | {IS_NIGHTLY_BUILD ? <NightlyMobileBetaRow /> : null} | 3343 | {IS_NIGHTLY_BUILD ? <NightlyMobileBetaRow /> : null} |
| 3343 | </> | 3344 | </> |
| 3344 | )} | 3345 | )} |
| 3346 | <SettingsRow | ||
| 3347 | {...searchableSetting("privacy-policy")} | ||
| 3348 | description="How we handle your data, including the anonymous usage data T3 Code collects." | ||
| 3349 | control={ | ||
| 3350 | <Button | ||
| 3351 | render={<a href={PRIVACY_POLICY_URL} target="_blank" rel="noreferrer noopener" />} | ||
| 3352 | size="sm" | ||
| 3353 | variant="outline" | ||
| 3354 | > | ||
| 3355 | View policy | ||
| 3356 | </Button> | ||
| 3357 | } | ||
| 3358 | /> | ||
| 3345 | </SettingsSection> | 3359 | </SettingsSection> |
| 3346 | <SettingsSection title="Diagnostics"> | 3360 | <SettingsSection title="Diagnostics"> |
| 3347 | <SettingsRow | 3361 | <SettingsRow |
apps/web/src/components/settings/settingsSearch.ts+6| ... | @@ -503,6 +503,12 @@ export const SETTINGS_SEARCH_ITEMS = [ | ... | @@ -503,6 +503,12 @@ export const SETTINGS_SEARCH_ITEMS = [ |
| 503 | scope: "project-defaults", | 503 | scope: "project-defaults", |
| 504 | searchTerms: ["generated thread titles source control content default provider"], | 504 | searchTerms: ["generated thread titles source control content default provider"], |
| 505 | }, | 505 | }, |
| 506 | { | ||
| 507 | id: "privacy-policy", | ||
| 508 | title: "Privacy policy", | ||
| 509 | to: "/settings/general", | ||
| 510 | searchTerms: ["telemetry analytics usage data tracking legal opt out"], | ||
| 511 | }, | ||
| 506 | { | 512 | { |
| 507 | id: "diagnostics", | 513 | id: "diagnostics", |
| 508 | title: "Diagnostics", | 514 | title: "Diagnostics", |
apps/web/src/legalLinks.ts created+1| ... | @@ -0,0 +1 @@ | ||
| 1 | export const PRIVACY_POLICY_URL = "https://t3.codes/privacy-policy"; | ||