Skip to content

Commit d70dba4

Browse files
Matt Morrismeta-codesync[bot]
authored andcommitted
Show diff view buttons on browser platform
Summary: On browser platforms (sl web), the per-file "Open Diff View" buttons were hidden because BrowserPlatform doesn't implement the optional openDiff method. This meant users had no per-file shortcut to view diffs — only the "View Changes" button that shows all files. This adds a single-file mode to the ComparisonView. When openDiff is unavailable, clicking a per-file diff button calls showComparisonForFile(), which opens the ComparisonView filtered to just that file. Multi-file UI (expand/collapse all buttons) is hidden in this mode. Changes: - atoms.ts: Added focusedFile to ComparisonMode, added showComparisonForFile() - ComparisonView.tsx: Filters file list when focusedFile is set, hides expand/collapse buttons - ComparisonViewModal.tsx: Passes focusedFile through to ComparisonView - ChangedFile.tsx: Per-file buttons fall back to showComparisonForFile() when openDiff is unavailable - BrowserPlatform.ts: Reverted to original (no platform-level changes needed) Reviewed By: evangrayk Differential Revision: D97681255 fbshipit-source-id: 1490258805caba066fb28f5dfd2b1ce39c25b1ca
1 parent a5f4b0f commit d70dba4

4 files changed

Lines changed: 69 additions & 36 deletions

File tree

addons/isl/src/ChangedFile.tsx

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ import {useContextMenu} from 'shared/ContextMenu';
2424
import {basename, notEmpty} from 'shared/utils';
2525
import {copyUrlForFile, supportsBrowseUrlForHash} from './BrowseRepo';
2626
import {type ChangedFilesDisplayType} from './ChangedFileDisplayTypePicker';
27+
import {showComparison} from './ComparisonView/atoms';
2728
import {generatedStatusDescription, generatedStatusToLabel} from './GeneratedFile';
2829
import {PartialFileSelectionWithMode} from './PartialFileSelection';
2930
import {confirmSuggestedEditsForFiles} from './SuggestedEdits';
@@ -103,12 +104,18 @@ export function File({
103104
onClick: () => platform.revealInExplorerView?.(file.path),
104105
});
105106
}
106-
if (comparison != null && platform.openDiff != null) {
107+
if (comparison != null) {
107108
options.push({
108109
label: t('Open Diff View ($comparison)', {
109110
replace: {$comparison: labelForComparison(comparison)},
110111
}),
111-
onClick: () => platform.openDiff?.(file.path, comparison),
112+
onClick: () => {
113+
if (platform.openDiff != null) {
114+
platform.openDiff(file.path, comparison);
115+
} else {
116+
showComparison(comparison, file.path);
117+
}
118+
},
112119
});
113120
}
114121

@@ -226,15 +233,19 @@ function FileActions({
226233

227234
const actions: Array<React.ReactNode> = [];
228235

229-
if (platform.openDiff != null && !conflictStatuses.has(file.status)) {
236+
if (!conflictStatuses.has(file.status)) {
230237
actions.push(
231238
<Tooltip title={t('Open diff view')} key="open-diff-view" delayMs={1000}>
232239
<Button
233240
className="file-show-on-hover"
234241
icon
235242
data-testid="file-open-diff-button"
236243
onClick={() => {
237-
platform.openDiff?.(file.path, comparison);
244+
if (platform.openDiff != null) {
245+
platform.openDiff(file.path, comparison);
246+
} else {
247+
showComparison(comparison, file.path);
248+
}
238249
}}>
239250
<Icon icon="request-changes" />
240251
</Button>

addons/isl/src/ComparisonView/ComparisonView.tsx

Lines changed: 37 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -74,9 +74,11 @@ const comparisonDisplayMode = localStorageBackedAtom<ComparisonDisplayMode | 're
7474
export default function ComparisonView({
7575
comparison,
7676
dismiss,
77+
focusedFile,
7778
}: {
7879
comparison: Comparison;
7980
dismiss?: () => void;
81+
focusedFile?: string;
8082
}) {
8183
const compared = useAtomValue(currentComparisonData(comparison));
8284

@@ -116,7 +118,10 @@ export default function ComparisonView({
116118
</EmptyState>
117119
);
118120
} else {
119-
const files = data.value ?? [];
121+
let files = data.value ?? [];
122+
if (focusedFile != null) {
123+
files = files.filter(f => f.newFileName === focusedFile || f.oldFileName === focusedFile);
124+
}
120125
sortFilesByType(files);
121126
const fileGroups = group(files, file => generatedStatuses[file.newFileName ?? '']);
122127
content = (
@@ -171,6 +176,7 @@ export default function ComparisonView({
171176
collapsedFiles={collapsedFiles}
172177
setCollapsedFile={setCollapsedFile}
173178
dismiss={dismiss}
179+
focusedFile={focusedFile}
174180
/>
175181
<div className="comparison-view-details">{content}</div>
176182
</div>
@@ -187,11 +193,13 @@ function ComparisonViewHeader({
187193
collapsedFiles,
188194
setCollapsedFile,
189195
dismiss,
196+
focusedFile,
190197
}: {
191198
comparison: Comparison;
192199
collapsedFiles: Map<string, boolean>;
193200
setCollapsedFile: (path: string, collapsed: boolean) => unknown;
194201
dismiss?: () => void;
202+
focusedFile?: string;
195203
}) {
196204
const setComparisonMode = useSetAtom(currentComparisonMode);
197205
const [compared, reloadComparison] = useAtom(currentComparisonData(comparison));
@@ -250,32 +258,36 @@ function ComparisonViewHeader({
250258
<Icon icon="refresh" data-testid="comparison-refresh-button" />
251259
</Button>
252260
</Tooltip>
253-
<Button
254-
onClick={() => {
255-
for (const file of data?.value ?? []) {
256-
if (file.newFileName) {
257-
setCollapsedFile(file.newFileName, false);
261+
{focusedFile == null && (
262+
<Button
263+
onClick={() => {
264+
for (const file of data?.value ?? []) {
265+
if (file.newFileName) {
266+
setCollapsedFile(file.newFileName, false);
267+
}
258268
}
259-
}
260-
}}
261-
disabled={isLoading || allFilesExpanded}
262-
icon>
263-
<Icon icon="unfold" slot="start" />
264-
<T>Expand all files</T>
265-
</Button>
266-
<Button
267-
onClick={() => {
268-
for (const file of data?.value ?? []) {
269-
if (file.newFileName) {
270-
setCollapsedFile(file.newFileName, true);
269+
}}
270+
disabled={isLoading || allFilesExpanded}
271+
icon>
272+
<Icon icon="unfold" slot="start" />
273+
<T>Expand all files</T>
274+
</Button>
275+
)}
276+
{focusedFile == null && (
277+
<Button
278+
onClick={() => {
279+
for (const file of data?.value ?? []) {
280+
if (file.newFileName) {
281+
setCollapsedFile(file.newFileName, true);
282+
}
271283
}
272-
}
273-
}}
274-
icon
275-
disabled={isLoading || noFilesExpanded}>
276-
<Icon icon="fold" slot="start" />
277-
<T>Collapse all files</T>
278-
</Button>
284+
}}
285+
icon
286+
disabled={isLoading || noFilesExpanded}>
287+
<Icon icon="fold" slot="start" />
288+
<T>Collapse all files</T>
289+
</Button>
290+
)}
279291
<Tooltip trigger="click" component={() => <ComparisonSettingsDropdown />}>
280292
<Button icon>
281293
<Icon icon="ellipsis" />

addons/isl/src/ComparisonView/ComparisonViewModal.tsx

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,11 @@ export function ComparisonViewModal() {
4545
return (
4646
<Modal className="comparison-view-modal" height="" width="">
4747
<Suspense fallback={<Icon icon="loading" />}>
48-
<ComparisonView comparison={mode.comparison} dismiss={dismissComparison} />
48+
<ComparisonView
49+
comparison={mode.comparison}
50+
dismiss={dismissComparison}
51+
focusedFile={mode.focusedFile}
52+
/>
4953
</Suspense>
5054
</Modal>
5155
);
@@ -61,7 +65,7 @@ export function ComparisonViewApp() {
6165
return (
6266
<div className="comparison-view-root">
6367
<Suspense fallback={<Icon icon="loading" />}>
64-
<ComparisonView comparison={mode.comparison} />
68+
<ComparisonView comparison={mode.comparison} focusedFile={mode.focusedFile} />
6569
</Suspense>
6670
</div>
6771
);

addons/isl/src/ComparisonView/atoms.ts

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6,13 +6,19 @@
66
*/
77

88
import type {Comparison} from 'shared/Comparison';
9+
import type {RepoRelativePath} from '../types';
910

1011
import {atom} from 'jotai';
1112
import {ComparisonType} from 'shared/Comparison';
1213
import {writeAtom} from '../jotaiUtils';
1314
import platform from '../platform';
1415

15-
export type ComparisonMode = {comparison: Comparison; visible: boolean};
16+
export type ComparisonMode = {
17+
comparison: Comparison;
18+
visible: boolean;
19+
/** When set, only show the diff for this specific file. */
20+
focusedFile?: RepoRelativePath;
21+
};
1622
export const currentComparisonMode = atom<ComparisonMode>(
1723
window.islAppMode?.mode === 'comparison'
1824
? {
@@ -25,14 +31,14 @@ export const currentComparisonMode = atom<ComparisonMode>(
2531
},
2632
);
2733

28-
/** Open Comparison View for a given comparison type */
29-
export async function showComparison(comparison: Comparison) {
34+
/** Open Comparison View, optionally focused on a single file */
35+
export async function showComparison(comparison: Comparison, focusedFile?: RepoRelativePath) {
3036
if (await platform.openDedicatedComparison?.(comparison)) {
3137
return;
3238
}
33-
writeAtom(currentComparisonMode, {comparison, visible: true});
39+
writeAtom(currentComparisonMode, {comparison, visible: true, focusedFile});
3440
}
3541

3642
export function dismissComparison() {
37-
writeAtom(currentComparisonMode, last => ({...last, visible: false}));
43+
writeAtom(currentComparisonMode, last => ({...last, visible: false, focusedFile: undefined}));
3844
}

0 commit comments

Comments
 (0)