addons/isl/src/ComparisonView/SplitDiffView/index.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 './SplitDiffHunk.css';
b69ab319
b69ab3110import {guessIsSubmodule} from 'shared/patch/parse';
b69ab3111import {type ParsedDiff} from 'shared/patch/types';
b69ab3112import type {Context} from './types';
b69ab3113
b69ab3114import {Button} from 'isl-components/Button';
b69ab3115import {Icon} from 'isl-components/Icon';
b69ab3116import {Tooltip} from 'isl-components/Tooltip';
b69ab3117import {useState} from 'react';
b69ab3118import {generatedStatusDescription} from '../../GeneratedFile';
b69ab3119import {T, t} from '../../i18n';
b69ab3120import platform from '../../platform';
b69ab3121import {GeneratedStatus} from '../../types';
b69ab3122import {FileHeader, diffTypeToIconType} from './SplitDiffFileHeader';
b69ab3123import {SplitDiffTable} from './SplitDiffHunk';
b69ab3124
b69ab3125export function SplitDiffView({
b69ab3126 ctx,
b69ab3127 path,
b69ab3128 patch,
b69ab3129 generatedStatus,
b69ab3130}: {
b69ab3131 ctx: Context;
b69ab3132 path: string;
b69ab3133 patch: ParsedDiff;
b69ab3134 generatedStatus?: GeneratedStatus;
b69ab3135}) {
b69ab3136 const fileName = patch.newFileName ?? patch.oldFileName ?? '/dev/null';
b69ab3137 // whether the file is manually or automatically collapsed by the chevron
b69ab3138 const collapsed = ctx.collapsed;
b69ab3139
b69ab3140 const isGenerated = generatedStatus != null && generatedStatus === GeneratedStatus.Generated;
b69ab3141 // whether the file content is collapsed due to being generated
b69ab3142 const [isContentCollapsed, setIsContentCollapsed] = useState(isGenerated);
b69ab3143
b69ab3144 const preamble = [];
b69ab3145 if (generatedStatus != null && generatedStatus !== GeneratedStatus.Manual) {
b69ab3146 preamble.push(
b69ab3147 <FileStatusBanner key="generated" color={'modified'}>
b69ab3148 <div>{generatedStatusDescription(generatedStatus)}</div>
b69ab3149 {isContentCollapsed ? (
b69ab3150 <Button icon onClick={() => setIsContentCollapsed(false)}>
b69ab3151 <T>Show anyway</T>
b69ab3152 </Button>
b69ab3153 ) : null}
b69ab3154 </FileStatusBanner>,
b69ab3155 );
b69ab3156 }
b69ab3157
b69ab3158 const isSubmodule = guessIsSubmodule(patch);
b69ab3159 const fileActions = (
b69ab3160 <>
b69ab3161 {platform.openDiff == null ? null : (
b69ab3162 <Tooltip title={t('Open diff view for file')} placement={'bottom'}>
b69ab3163 <Button
b69ab3164 icon
b69ab3165 className="split-diff-view-file-header-open-diff-button"
b69ab3166 onClick={() => {
b69ab3167 platform.openDiff?.(path, ctx.id.comparison);
b69ab3168 }}>
b69ab3169 <Icon icon="git-pull-request-go-to-changes" />
b69ab3170 </Button>
b69ab3171 </Tooltip>
b69ab3172 )}
b69ab3173 {!isSubmodule && (
b69ab3174 <Tooltip title={t('Open file')} placement={'bottom'}>
b69ab3175 <Button
b69ab3176 icon
b69ab3177 className="split-diff-view-file-header-open-button"
b69ab3178 onClick={() => {
b69ab3179 platform.openFile(path);
b69ab3180 }}>
b69ab3181 <Icon icon="go-to-file" />
b69ab3182 </Button>
b69ab3183 </Tooltip>
b69ab3184 )}
b69ab3185 </>
b69ab3186 );
b69ab3187
b69ab3188 const copyFrom = patch.oldFileName === fileName ? undefined : patch.oldFileName;
b69ab3189 const iconType = diffTypeToIconType(patch.type);
b69ab3190 return (
b69ab3191 <div className="split-diff-view">
b69ab3192 <FileHeader
b69ab3193 path={fileName}
b69ab3194 copyFrom={copyFrom}
b69ab3195 iconType={iconType}
b69ab3196 open={!collapsed}
b69ab3197 onChangeOpen={open => ctx.setCollapsed(!open)}
b69ab3198 fileActions={fileActions}
b69ab3199 />
b69ab31100 {!collapsed && preamble && <div className="split-diff-view-file-preamble">{preamble}</div>}
b69ab31101 {!collapsed && !isContentCollapsed && <SplitDiffTable ctx={ctx} path={path} patch={patch} />}
b69ab31102 </div>
b69ab31103 );
b69ab31104}
b69ab31105
b69ab31106function FileStatusBanner({
b69ab31107 children,
b69ab31108 color,
b69ab31109}: {
b69ab31110 children: React.ReactNode;
b69ab31111 color: 'added' | 'removed' | 'modified';
b69ab31112}): React.ReactElement {
b69ab31113 return (
b69ab31114 <div className={`split-diff-view-file-status-banner split-diff-view-banner-${color}`}>
b69ab31115 {children}
b69ab31116 </div>
b69ab31117 );
b69ab31118}