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