| 1 | /** |
| 2 | * Copyright (c) Meta Platforms, Inc. and affiliates. |
| 3 | * |
| 4 | * This source code is licensed under the MIT license found in the |
| 5 | * LICENSE file in the root directory of this source tree. |
| 6 | */ |
| 7 | |
| 8 | import type {Json} from 'shared/typeUtils'; |
| 9 | |
| 10 | import {Checkbox} from 'isl-components/Checkbox'; |
| 11 | import {Dropdown} from 'isl-components/Dropdown'; |
| 12 | import {Column} from 'isl-components/Flex'; |
| 13 | import {Tooltip} from 'isl-components/Tooltip'; |
| 14 | import {shouldWarnAboutDiagnosticsAtom} from 'isl/src/Diagnostics'; |
| 15 | import {Setting} from 'isl/src/Setting'; |
| 16 | import {T, t} from 'isl/src/i18n'; |
| 17 | import {writeAtom} from 'isl/src/jotaiUtils'; |
| 18 | import {atom, useAtom, useAtomValue} from 'jotai'; |
| 19 | import serverAPI from '../../isl/src/ClientToServerAPI'; |
| 20 | import {ComparisonPanelMode, comparisonPanelMode, setComparisonPanelMode} from './state'; |
| 21 | |
| 22 | export default function VSCodeSettings() { |
| 23 | const panelMode = useAtomValue(comparisonPanelMode); |
| 24 | const [openBesides, setOpenBesides] = useAtom(openBesidesSetting); |
| 25 | const [checkDiagnostics, setCheckDiagnostics] = useAtom(shouldWarnAboutDiagnosticsAtom); |
| 26 | return ( |
| 27 | <Setting title={<T>VS Code Settings</T>}> |
| 28 | <Column alignStart> |
| 29 | <Tooltip |
| 30 | title={t( |
| 31 | 'Whether to always open a separate panel to view comparisons, or to open the comparison inside an existing ISL window.', |
| 32 | )}> |
| 33 | <div className="dropdown-container setting-inline-dropdown"> |
| 34 | <label> |
| 35 | <T>Comparison Panel Mode</T> |
| 36 | </label> |
| 37 | <Dropdown |
| 38 | options={Object.values(ComparisonPanelMode).map(name => ({name, value: name}))} |
| 39 | value={panelMode} |
| 40 | onChange={event => |
| 41 | setComparisonPanelMode(event.currentTarget.value as ComparisonPanelMode) |
| 42 | } |
| 43 | /> |
| 44 | </div> |
| 45 | </Tooltip> |
| 46 | <Tooltip |
| 47 | title={t( |
| 48 | 'If true, files, diffs, and comparisons will open beside the existing ISL panel instead of in the same View Column. Useful to keep ISL open and visible when clicking on files.', |
| 49 | )}> |
| 50 | <Checkbox checked={openBesides} onChange={checked => setOpenBesides(checked)}> |
| 51 | <T>Open Besides</T> |
| 52 | </Checkbox> |
| 53 | </Tooltip> |
| 54 | <Tooltip |
| 55 | title={t( |
| 56 | 'If true, check VS Code language diagnostics for the files that would be committed / amended. This is best-effort, and only works on files that are already open in VS Code.', |
| 57 | )}> |
| 58 | <Checkbox checked={checkDiagnostics} onChange={checked => setCheckDiagnostics(checked)}> |
| 59 | <T>Check diagnostics before committing / amending</T> |
| 60 | </Checkbox> |
| 61 | </Tooltip> |
| 62 | </Column> |
| 63 | </Setting> |
| 64 | ); |
| 65 | } |
| 66 | |
| 67 | const openBesidesSetting = vscodeConfigBackedAtom<boolean>('sapling.isl.openBeside', false); |
| 68 | |
| 69 | function vscodeConfigBackedAtom<T extends Json>( |
| 70 | configName: string, |
| 71 | defaultValue: T, |
| 72 | scope: 'global' | 'workspace' = 'global', |
| 73 | ) { |
| 74 | const primitiveAtom = atom<T>(defaultValue); |
| 75 | |
| 76 | serverAPI.postMessage({ |
| 77 | type: 'platform/subscribeToVSCodeConfig', |
| 78 | config: configName, |
| 79 | }); |
| 80 | serverAPI.onMessageOfType('platform/vscodeConfigChanged', config => { |
| 81 | if (config.config === configName) { |
| 82 | writeAtom(primitiveAtom, config.value as T); |
| 83 | } |
| 84 | }); |
| 85 | |
| 86 | return atom<T, [T | ((prev: T) => T)], void>( |
| 87 | get => get(primitiveAtom), |
| 88 | (get, set, update) => { |
| 89 | const newValue = typeof update === 'function' ? update(get(primitiveAtom)) : update; |
| 90 | set(primitiveAtom, newValue); |
| 91 | serverAPI.postMessage({ |
| 92 | type: 'platform/setVSCodeConfig', |
| 93 | config: configName, |
| 94 | value: newValue, |
| 95 | scope, |
| 96 | }); |
| 97 | }, |
| 98 | ); |
| 99 | } |
| 100 | |