2639 lines · 98.1 KB · TypeScript
RawDownload
import { ArchiveIcon, ArchiveX, ChevronRightIcon, LoaderIcon, SettingsIcon } from "lucide-react";import { Link } from "@tanstack/react-router";import type { CSSProperties, ReactNode } from "react";import { useCallback, useEffect, useMemo, useRef, useState } from "react";import { useAtomValue } from "@effect/atom-react";import {  type BackgroundActivityProfile,  type DesktopUpdateChannel,  ProviderDriverKind,  type ScopedThreadRef,  type SidebarProjectGroupingMode,} from "@t3tools/contracts";import { scopeThreadRef } from "@t3tools/client-runtime/environment";import {  isAtomCommandInterrupted,  settlePromise,  squashAtomCommandFailure,} from "@t3tools/client-runtime/state/runtime";import {  DEFAULT_ENVIRONMENT_IDENTIFICATION_MODE,  DEFAULT_UNIFIED_SETTINGS,  type EnvironmentIdentificationMode,  MAX_CODE_FONT_SIZE,  MAX_GLASS_OPACITY,  MAX_INTERFACE_FONT_SIZE,  MAX_PROMPT_FONT_SIZE,  MAX_SIDEBAR_AUTO_SETTLE_AFTER_DAYS,  MAX_TERMINAL_FONT_SIZE,  MIN_CODE_FONT_SIZE,  MIN_GLASS_OPACITY,  MIN_INTERFACE_FONT_SIZE,  MIN_PROMPT_FONT_SIZE,  MIN_SIDEBAR_AUTO_SETTLE_AFTER_DAYS,  MIN_TERMINAL_FONT_SIZE,} from "@t3tools/contracts/settings";import { resolveServerBackgroundActivitySettings } from "@t3tools/shared/backgroundActivitySettings";import { createModelSelection } from "@t3tools/shared/model";import * as Duration from "effect/Duration";import * as Equal from "effect/Equal";import * as Schema from "effect/Schema";import { APP_VERSION, HOSTED_APP_CHANNEL, HOSTED_APP_CHANNEL_LABEL } from "../../branding";import {  canCheckForUpdate,  getDesktopUpdateButtonTooltip,  getDesktopUpdateInstallConfirmationMessage,  isDesktopUpdateButtonDisabled,  resolveDesktopUpdateButtonAction,} from "../../components/desktopUpdate.logic";import { ProviderModelPicker } from "../chat/ProviderModelPicker";import { TraitsPicker } from "../chat/TraitsPicker";import {  resolveEnvironmentIdentificationPillLabel,  useEnvironmentStageLabel,} from "../SidebarStageBackdrop";import { isElectron } from "../../env";import { buildHostedChannelSelectionUrl, type HostedAppChannel } from "../../hostedPairing";import { useCustomThemes } from "../../hooks/useCustomThemes";import {  readAppearanceModePreference,  readThemeHalves,  readThemePreference,  useTheme,} from "../../hooks/useTheme";import { useLocalStorage } from "../../hooks/useLocalStorage";import { usePrimarySettings, useUpdatePrimarySettings } from "../../hooks/useSettings";import { useThreadActions } from "../../hooks/useThreadActions";import { useDesktopUpdateState } from "../../state/desktopUpdate";import {  getCustomModelOptionsByInstance,  resolveAppModelSelectionState,  withoutPlanAgentSelection,} from "../../modelSelection";import {  applyProviderInstanceSettings,  deriveProviderInstanceEntries,  sortProviderInstanceEntries,} from "../../providerInstances";import { ensureLocalApi, readLocalApi } from "../../localApi";import { isMacPlatform } from "../../lib/utils";import { primaryServerObservabilityAtom, primaryServerProvidersAtom } from "../../state/server";import { useProjects } from "../../state/entities";import { useArchivedThreadSnapshots } from "../../lib/archivedThreadsState";import { formatRelativeTimeLabel } from "../../timestampFormat";import { Button } from "../ui/button";import { Collapsible, CollapsiblePanel, CollapsibleTrigger } from "../ui/collapsible";import {  Dialog,  DialogDescription,  DialogFooter,  DialogHeader,  DialogPanel,  DialogPopup,  DialogTitle,} from "../ui/dialog";import { DraftInput } from "../ui/draft-input";import { Input } from "../ui/input";import {  DEFAULT_CODE_FONT_STACK,  DEFAULT_SANS_FONT_STACK,  isFontFamilyAvailable,  isMonospaceFamily,  resolveDefaultFamilyLabel,  resolveTerminalFontPreference,  resolveTerminalFontSizePreference,  TYPOGRAPHY_ADVANCED_STORAGE_KEY,} from "../../appearanceFonts";import { CodeFontPreview, PromptFontPreview, TerminalFontPreview } from "./SettingsFontPreviews";import { discoverInstalledFonts, FontFamilyPicker, useFontEnumeration } from "./FontFamilyPicker";import {  NumberField,  NumberFieldDecrement,  NumberFieldGroup,  NumberFieldIncrement,  NumberFieldInput,} from "../ui/number-field";import { Select, SelectItem, SelectPopup, SelectTrigger, SelectValue } from "../ui/select";import { Switch } from "../ui/switch";import { stackedThreadToast, toastManager } from "../ui/toast";import { Tooltip, TooltipPopup, TooltipTrigger } from "../ui/tooltip";import { ThemeLibrary } from "./ThemeSettings";import {  backgroundActivityOverrideSettings,  backgroundActivitySharedPolicySettings,  durationToSeconds,  formatDiagnosticsDescription,  getChangedBrowserSettingLabels,  getChangedTypographySettingLabels,  normalizeIntervalSeconds,  PROVIDER_HEALTH_INTERVAL_STEP_SECONDS,  hasChangedBackgroundActivitySettings,  isProjectGroupingEnabled,  projectGroupingModeFromToggle,  readLastEnabledProjectGroupingMode,  rememberEnabledProjectGroupingMode,  resolveBackgroundActivityProfileOption,} from "./SettingsPanels.logic";import {  PolicyTooltip,  SettingResetButton,  SettingsPageContainer,  SettingsRow,  SettingsSection,  useSettingsSearchTargetId,} from "./settingsLayout";import { searchableSetting } from "./settingsSearch";import { ProjectFavicon } from "../ProjectFavicon"; const ENVIRONMENT_IDENTIFICATION_LABELS: Record<EnvironmentIdentificationMode, string> = {  artwork: "Artwork",  pill: "Version pill",  none: "None",}; const TIMESTAMP_FORMAT_LABELS = {  locale: "System default",  "12-hour": "12-hour",  "24-hour": "24-hour",} as const; const BACKGROUND_ACTIVITY_PROFILE_LABELS: Record<BackgroundActivityProfile, string> = {  balanced: "Balanced",  performance: "Performance",  "battery-saver": "Battery saver",}; type BackgroundActivityProfileOption = BackgroundActivityProfile | "advanced"; const BACKGROUND_ACTIVITY_PROFILE_OPTION_LABELS: Record<BackgroundActivityProfileOption, string> = {  ...BACKGROUND_ACTIVITY_PROFILE_LABELS,  advanced: "Advanced",}; const BACKGROUND_ACTIVITY_PROFILE_DESCRIPTIONS: Record<BackgroundActivityProfile, string> = {  balanced:    "Pauses background probes when clients are idle, the host is locked, or low power mode is active.",  performance: "Allows scoped background probes while any subscribed client remains connected.",  "battery-saver": "Also pauses background probes when the host or client is on battery.",}; const ADVANCED_BACKGROUND_ACTIVITY_DESCRIPTION =  "Uses custom background intervals with the selected shared power policy."; const DEFAULT_DRIVER_KIND = ProviderDriverKind.make("codex");const BACKGROUND_ACTIVITY_BOOLEAN_OVERRIDES: ReadonlyArray<{  readonly key:    | "pauseWhenHostLocked"    | "pauseWhenHostLowPower"    | "pauseWhenClientLowPower"    | "pauseWhenOnBattery";  readonly label: string;}> = [  { key: "pauseWhenHostLocked", label: "Pause when host is locked" },  { key: "pauseWhenHostLowPower", label: "Pause on host low power" },  { key: "pauseWhenClientLowPower", label: "Pause on client low power" },  { key: "pauseWhenOnBattery", label: "Pause on battery" },]; function resetBackgroundActivitySettings() {  return {    backgroundActivity: DEFAULT_UNIFIED_SETTINGS.backgroundActivity,  };} function backgroundActivityProfileSettings(profile: BackgroundActivityProfile) {  return {    backgroundActivity: {      schemaVersion: 1 as const,      profile,      overrides: {},    },  };} function AboutVersionTitle() {  return (    <span className="inline-flex items-baseline gap-2">      <span>Version</span>      <code className="text-[11px] font-medium text-muted-foreground">{APP_VERSION}</code>    </span>  );} function AboutVersionSection() {  const updateState = useDesktopUpdateState();  const [isChangingUpdateChannel, setIsChangingUpdateChannel] = useState(false);  const [isUpdateActionPending, setIsUpdateActionPending] = useState(false);   const hasDesktopBridge = typeof window !== "undefined" && Boolean(window.desktopBridge);  const selectedUpdateChannel = updateState?.channel ?? "latest";  const selectedHostedAppChannel = hasDesktopBridge ? null : HOSTED_APP_CHANNEL;   const handleUpdateChannelChange = useCallback(    (channel: DesktopUpdateChannel) => {      const bridge = window.desktopBridge;      if (        !bridge ||        typeof bridge.setUpdateChannel !== "function" ||        channel === selectedUpdateChannel      ) {        return;      }       setIsChangingUpdateChannel(true);      void bridge        .setUpdateChannel(channel)        .catch((error: unknown) => {          toastManager.add(            stackedThreadToast({              type: "error",              title: "Could not change update track",              description: error instanceof Error ? error.message : "Update track change failed.",            }),          );        })        .finally(() => {          setIsChangingUpdateChannel(false);        });    },    [selectedUpdateChannel],  );   const handleButtonClick = useCallback(async () => {    const bridge = window.desktopBridge;    if (!bridge) return;     const action = updateState ? resolveDesktopUpdateButtonAction(updateState) : "none";     if (action === "download") {      void bridge.downloadUpdate().catch((error: unknown) => {        toastManager.add(          stackedThreadToast({            type: "error",            title: "Could not download update",            description: error instanceof Error ? error.message : "Download failed.",          }),        );      });      return;    }     if (action === "install") {      if (isUpdateActionPending) return;      setIsUpdateActionPending(true);      let confirmed = false;      try {        confirmed = await ensureLocalApi().dialogs.confirm(          getDesktopUpdateInstallConfirmationMessage(            updateState ?? { availableVersion: null, downloadedVersion: null },          ),        );      } catch (error) {        setIsUpdateActionPending(false);        toastManager.add(          stackedThreadToast({            type: "error",            title: "Could not confirm update",            description: error instanceof Error ? error.message : "Update confirmation failed.",          }),        );        return;      }      if (!confirmed) {        setIsUpdateActionPending(false);        return;      }      void bridge        .installUpdate()        .catch((error: unknown) => {          toastManager.add(            stackedThreadToast({              type: "error",              title: "Could not install update",              description: error instanceof Error ? error.message : "Install failed.",            }),          );        })        .finally(() => setIsUpdateActionPending(false));      return;    }     if (typeof bridge.checkForUpdate !== "function") return;    void bridge      .checkForUpdate()      .then((result) => {        if (!result.checked) {          toastManager.add(            stackedThreadToast({              type: "error",              title: "Could not check for updates",              description:                result.state.message ?? "Automatic updates are not available in this build.",            }),          );        }      })      .catch((error: unknown) => {        toastManager.add(          stackedThreadToast({            type: "error",            title: "Could not check for updates",            description: error instanceof Error ? error.message : "Update check failed.",          }),        );      });  }, [isUpdateActionPending, updateState]);   const action = updateState ? resolveDesktopUpdateButtonAction(updateState) : "none";  const buttonTooltip = updateState ? getDesktopUpdateButtonTooltip(updateState) : null;  const buttonDisabled =    action === "none"      ? !canCheckForUpdate(updateState)      : isDesktopUpdateButtonDisabled(updateState);   const actionLabel: Record<string, string> = { download: "Download", install: "Install" };  const statusLabel: Record<string, string> = {    checking: "Checking…",    downloading: "Downloading…",    "up-to-date": "Up to Date",  };  const buttonLabel =    actionLabel[action] ?? statusLabel[updateState?.status ?? ""] ?? "Check for Updates";  const description =    action === "download" || action === "install"      ? "Update available."      : "Current version of the application.";   return (    <>      <SettingsRow        title={<AboutVersionTitle />}        description={description}        control={          <Tooltip>            <TooltipTrigger              render={                <Button                  size="xs"                  variant={action === "install" ? "default" : "outline"}                  disabled={buttonDisabled || isUpdateActionPending}                  onClick={handleButtonClick}                >                  {buttonLabel}                </Button>              }            />            {buttonTooltip ? <TooltipPopup>{buttonTooltip}</TooltipPopup> : null}          </Tooltip>        }      />      {hasDesktopBridge ? (        <SettingsRow          title="Update track"          description="Stable follows full releases. Nightly follows the nightly desktop channel and can switch back to stable immediately."          control={            <Select              value={selectedUpdateChannel}              onValueChange={(value) => {                handleUpdateChannelChange(value as DesktopUpdateChannel);              }}            >              <SelectTrigger                className="w-full sm:w-40"                aria-label="Update track"                disabled={isChangingUpdateChannel}              >                <SelectValue>                  {selectedUpdateChannel === "nightly" ? "Nightly" : "Stable"}                </SelectValue>              </SelectTrigger>              <SelectPopup align="end" alignItemWithTrigger={false}>                <SelectItem hideIndicator value="latest">                  Stable                </SelectItem>                <SelectItem hideIndicator value="nightly">                  Nightly                </SelectItem>              </SelectPopup>            </Select>          }        />      ) : selectedHostedAppChannel ? (        <SettingsRow          title="Update track"          description="Switches the hosted app release channel."          control={            <Select              value={selectedHostedAppChannel}              onValueChange={(value) => {                if (value === selectedHostedAppChannel) return;                window.location.assign(                  buildHostedChannelSelectionUrl({ channel: value as HostedAppChannel }),                );              }}            >              <SelectTrigger className="w-full sm:w-40" aria-label="Update track">                <SelectValue>{HOSTED_APP_CHANNEL_LABEL}</SelectValue>              </SelectTrigger>              <SelectPopup align="end" alignItemWithTrigger={false}>                <SelectItem hideIndicator value="latest">                  Latest                </SelectItem>                <SelectItem hideIndicator value="nightly">                  Nightly                </SelectItem>              </SelectPopup>            </Select>          }        />      ) : null}    </>  );} export function useSettingsRestore(onRestored?: () => void) {  const {    theme,    setTheme,    followSystem,    setFollowSystem,    setThemeHalf,    clearThemeHalves,    themeHalves,  } = useTheme();  const settings = usePrimarySettings();  const updateSettings = useUpdatePrimarySettings();   const isTextGenerationModelDirty = !Equal.equals(    settings.textGenerationModelSelection ?? null,    DEFAULT_UNIFIED_SETTINGS.textGenerationModelSelection ?? null,  );  const isBackgroundActivityDirty = hasChangedBackgroundActivitySettings(settings);   const changedSettingLabels = useMemo(    () => [      ...(theme !== "system" ? ["Theme"] : []),      ...(!followSystem ? ["Follow system"] : []),      ...(themeHalves !== null ? ["Theme mix"] : []),      ...(settings.glassOpacity !== DEFAULT_UNIFIED_SETTINGS.glassOpacity ? ["Glass opacity"] : []),      ...(settings.environmentIdentificationMode !==      DEFAULT_UNIFIED_SETTINGS.environmentIdentificationMode        ? ["Environment identification"]        : []),      ...(settings.timestampFormat !== DEFAULT_UNIFIED_SETTINGS.timestampFormat        ? ["Time format"]        : []),      ...(settings.sidebarThreadPreviewCount !== DEFAULT_UNIFIED_SETTINGS.sidebarThreadPreviewCount        ? ["Visible threads"]        : []),      ...(settings.sidebarProjectGroupingMode !==      DEFAULT_UNIFIED_SETTINGS.sidebarProjectGroupingMode        ? ["Project Grouping"]        : []),      ...(settings.sidebarAutoSettleAfterDays !==      DEFAULT_UNIFIED_SETTINGS.sidebarAutoSettleAfterDays        ? ["Auto-settle inactive threads"]        : []),      ...(settings.sidebarAutoSettleOnMerge !== DEFAULT_UNIFIED_SETTINGS.sidebarAutoSettleOnMerge        ? ["Auto-settle merged threads"]        : []),      ...(settings.wordWrap !== DEFAULT_UNIFIED_SETTINGS.wordWrap ? ["Word wrap"] : []),

Lines 1–500 of 2639.