addons/isl/src/PullButton.tsxblame
View source
b69ab311/**
b69ab312 * Copyright (c) Meta Platforms, Inc. and affiliates.
b69ab313 *
b69ab314 * This source code is licensed under the MIT license found in the
b69ab315 * LICENSE file in the root directory of this source tree.
b69ab316 */
b69ab317
b69ab318import type {Operation} from './operations/Operation';
b69ab319
b69ab3110import {Button} from 'isl-components/Button';
b69ab3111import {ButtonDropdown} from 'isl-components/ButtonDropdown';
b69ab3112import {Icon} from 'isl-components/Icon';
b69ab3113import {DOCUMENTATION_DELAY, Tooltip} from 'isl-components/Tooltip';
b69ab3114import {useAtom, useAtomValue} from 'jotai';
b69ab3115import {fetchStableLocations} from './BookmarksData';
b69ab3116import {Internal} from './Internal';
b69ab3117import {t, T} from './i18n';
b69ab3118import {configBackedAtom} from './jotaiUtils';
b69ab3119import {PullOperation} from './operations/PullOperation';
b69ab3120import {useRunOperation} from './operationsState';
b69ab3121import {uncommittedChangesWithPreviews, useMostRecentPendingOperation} from './previews';
b69ab3122
b69ab3123import './PullButton.css';
b69ab3124
b69ab3125const DEFAULT_PULL_BUTTON = {
b69ab3126 id: 'pull',
b69ab3127 label: <T>Pull</T>,
b69ab3128 getOperation: () => new PullOperation(),
b69ab3129 isRunning: (op: Operation) => op instanceof PullOperation,
b69ab3130 tooltip: t('Fetch latest repository and branch information from remote.'),
b69ab3131 allowWithUncommittedChanges: true,
b69ab3132};
b69ab3133const pullButtonChoiceKey = configBackedAtom<string>(
b69ab3134 'isl.pull-button-choice',
b69ab3135 DEFAULT_PULL_BUTTON.id,
b69ab3136);
b69ab3137
b69ab3138export type PullButtonOption = {
b69ab3139 id: string;
b69ab3140 label: React.ReactNode;
b69ab3141 getOperation: () => Operation;
b69ab3142 isRunning: (op: Operation) => boolean;
b69ab3143 tooltip: string;
b69ab3144 allowWithUncommittedChanges: boolean;
b69ab3145};
b69ab3146
b69ab3147export function PullButton() {
b69ab3148 const runOperation = useRunOperation();
b69ab3149
b69ab3150 const pullButtonOptions: Array<PullButtonOption> = [];
b69ab3151 pullButtonOptions.push(DEFAULT_PULL_BUTTON, ...(Internal.additionalPullOptions ?? []));
b69ab3152
b69ab3153 const [dropdownChoiceKey, setDropdownChoiceKey] = useAtom(pullButtonChoiceKey);
b69ab3154 const currentChoice =
b69ab3155 pullButtonOptions.find(option => option.id === dropdownChoiceKey) ?? pullButtonOptions[0];
b69ab3156
b69ab3157 const trackedChanges = useAtomValue(uncommittedChangesWithPreviews).filter(
b69ab3158 change => change.status !== '?',
b69ab3159 );
b69ab3160 const hasUncommittedChanges = trackedChanges.length > 0;
b69ab3161
b69ab3162 const disabledFromUncommittedChanges =
b69ab3163 currentChoice.allowWithUncommittedChanges === false && hasUncommittedChanges;
b69ab3164
b69ab3165 let tooltip =
b69ab3166 currentChoice.tooltip +
b69ab3167 (disabledFromUncommittedChanges == false
b69ab3168 ? ''
b69ab3169 : '\n\n' + t('Disabled due to uncommitted changes.'));
b69ab3170 const pendingOperation = useMostRecentPendingOperation();
b69ab3171 const isRunningPull = pendingOperation != null && currentChoice.isRunning(pendingOperation);
b69ab3172 if (isRunningPull) {
b69ab3173 tooltip += '\n\n' + t('Pull is already running.');
b69ab3174 }
b69ab3175
b69ab3176 return (
b69ab3177 <Tooltip placement="bottom" delayMs={DOCUMENTATION_DELAY} title={tooltip}>
b69ab3178 <div className="pull-info">
b69ab3179 {pullButtonOptions.length > 1 ? (
b69ab3180 <ButtonDropdown
b69ab3181 buttonDisabled={!!isRunningPull || disabledFromUncommittedChanges}
b69ab3182 options={pullButtonOptions}
b69ab3183 onClick={() => {
b69ab3184 runOperation(currentChoice.getOperation());
b69ab3185 fetchStableLocations();
b69ab3186 }}
b69ab3187 onChangeSelected={choice => setDropdownChoiceKey(choice.id)}
b69ab3188 selected={currentChoice}
b69ab3189 icon={<Icon slot="start" icon={isRunningPull ? 'loading' : 'repo'} />}
b69ab3190 />
b69ab3191 ) : (
b69ab3192 <Button
b69ab3193 disabled={!!isRunningPull}
b69ab3194 onClick={() => {
b69ab3195 runOperation(new PullOperation());
b69ab3196 fetchStableLocations();
b69ab3197 }}>
b69ab3198 <Icon slot="start" icon={isRunningPull ? 'loading' : 'cloud-download'} />
b69ab3199 <T>Pull</T>
b69ab31100 </Button>
b69ab31101 )}
b69ab31102 </div>
b69ab31103 </Tooltip>
b69ab31104 );
b69ab31105}