Merge "Add DiffRangesToFocus as input to gr-diff to support collapsing unrelated diff changes."
diff --git a/polygerrit-ui/app/api/diff.ts b/polygerrit-ui/app/api/diff.ts
index 24110ed..90cf17b 100644
--- a/polygerrit-ui/app/api/diff.ts
+++ b/polygerrit-ui/app/api/diff.ts
@@ -552,3 +552,13 @@
     intentionalMove?: boolean
   ): void;
 }
+
+/**
+ * Represents a list of ranges in a diff that should be focused.
+ *
+ * This is used to collapse diff chunks that are not in focus.
+ */
+export declare interface DiffRangesToFocus {
+  left: {start: number; end: number}[];
+  right: {start: number; end: number}[];
+}
diff --git a/polygerrit-ui/app/embed/diff/gr-diff-model/gr-diff-model.ts b/polygerrit-ui/app/embed/diff/gr-diff-model/gr-diff-model.ts
index 88451f6..8488bd5 100644
--- a/polygerrit-ui/app/embed/diff/gr-diff-model/gr-diff-model.ts
+++ b/polygerrit-ui/app/embed/diff/gr-diff-model/gr-diff-model.ts
@@ -10,6 +10,7 @@
   DiffInfo,
   DiffLayer,
   DiffPreferencesInfo,
+  DiffRangesToFocus,
   DiffResponsiveMode,
   DiffViewMode,
   DisplayLine,
@@ -51,6 +52,7 @@
   renderPrefs: RenderPreferences;
   diffPrefs: DiffPreferencesInfo;
   lineOfInterest?: DisplayLine;
+  diffRangesToFocus?: DiffRangesToFocus;
   comments: GrDiffCommentThread[];
   groups: GrDiffGroup[];
   /** how much context to show for large files */
@@ -211,6 +213,9 @@
       computeKeyLocations(diffState.lineOfInterest, diffState.comments ?? [])
   );
 
+  readonly diffRangesToFocus$: Observable<DiffRangesToFocus | undefined> =
+    select(this.state$, diffState => diffState.diffRangesToFocus);
+
   constructor(
     /**
      * Normally a reference to the <gr-diff> component. Used for firing events
@@ -232,23 +237,31 @@
   }
 
   processDiff() {
-    return combineLatest([this.diff$, this.context$, this.renderPrefs$])
+    return combineLatest([
+      this.diff$,
+      this.context$,
+      this.renderPrefs$,
+      this.diffRangesToFocus$,
+    ])
       .pipe(
         withLatestFrom(this.keyLocations$),
         debounceTime(1),
-        map(([[diff, context, renderPrefs], keyLocations]) => {
-          const options: ProcessingOptions = {
-            context,
-            keyLocations,
-            isBinary: !!(isImageDiff(diff) || diff.binary),
-          };
-          if (renderPrefs?.num_lines_rendered_at_once) {
-            options.asyncThreshold = renderPrefs.num_lines_rendered_at_once;
-          }
+        map(
+          ([[diff, context, renderPrefs, diffRangesToFocus], keyLocations]) => {
+            const options: ProcessingOptions = {
+              context,
+              keyLocations,
+              isBinary: !!(isImageDiff(diff) || diff.binary),
+              diffRangesToFocus,
+            };
+            if (renderPrefs?.num_lines_rendered_at_once) {
+              options.asyncThreshold = renderPrefs.num_lines_rendered_at_once;
+            }
 
-          const processor = new GrDiffProcessor(options);
-          return processor.process(diff.content);
-        })
+            const processor = new GrDiffProcessor(options);
+            return processor.process(diff.content);
+          }
+        )
       )
       .subscribe(groups => {
         this.updateState({groups});
diff --git a/polygerrit-ui/app/embed/diff/gr-diff-processor/gr-diff-processor.ts b/polygerrit-ui/app/embed/diff/gr-diff-processor/gr-diff-processor.ts
index 6b7b45f..1561dad 100644
--- a/polygerrit-ui/app/embed/diff/gr-diff-processor/gr-diff-processor.ts
+++ b/polygerrit-ui/app/embed/diff/gr-diff-processor/gr-diff-processor.ts
@@ -9,7 +9,7 @@
   GrDiffGroupType,
   hideInContextControl,
 } from '../gr-diff/gr-diff-group';
-import {DiffContent} from '../../../types/diff';
+import {DiffContent, DiffRangesToFocus} from '../../../types/diff';
 import {Side} from '../../../constants/constants';
 import {getStringLength} from '../gr-diff-highlight/gr-annotation';
 import {GrDiffLineType, LineNumber} from '../../../api/diff';
@@ -41,6 +41,7 @@
   keyLocations?: KeyLocations;
   asyncThreshold?: number;
   isBinary?: boolean;
+  diffRangesToFocus?: DiffRangesToFocus;
 }
 
 /**
diff --git a/polygerrit-ui/app/embed/diff/gr-diff/gr-diff.ts b/polygerrit-ui/app/embed/diff/gr-diff/gr-diff.ts
index 90b9cfe..f3534c2 100644
--- a/polygerrit-ui/app/embed/diff/gr-diff/gr-diff.ts
+++ b/polygerrit-ui/app/embed/diff/gr-diff/gr-diff.ts
@@ -44,6 +44,7 @@
   RenderPreferences,
   GrDiff as GrDiffApi,
   DisplayLine,
+  DiffRangesToFocus,
   LineNumber,
   ContentLoadNeededEventDetail,
   DiffContextExpandedExternalDetail,
@@ -182,6 +183,9 @@
   @property({type: Object})
   lineOfInterest?: DisplayLine;
 
+  @property({type: Object})
+  diffRangesToFocus?: DiffRangesToFocus;
+
   /**
    * True when diff is changed, until the content is done rendering.
    * Use getter/setter loading instead of this.
@@ -368,7 +372,8 @@
       changedProperties.has('showNewlineWarningLeft') ||
       changedProperties.has('showNewlineWarningRight') ||
       changedProperties.has('prefs') ||
-      changedProperties.has('lineOfInterest')
+      changedProperties.has('lineOfInterest') ||
+      changedProperties.has('diffRangesToFocus')
     ) {
       if (this.diff && this.prefs) {
         const renderPrefs = {...(this.renderPrefs ?? {})};
@@ -394,6 +399,7 @@
           renderPrefs,
           diffPrefs: this.prefs,
           lineOfInterest: this.lineOfInterest,
+          diffRangesToFocus: this.diffRangesToFocus,
         });
       }
     }
diff --git a/polygerrit-ui/app/types/diff.ts b/polygerrit-ui/app/types/diff.ts
index 2a8c7e5..0d1592e 100644
--- a/polygerrit-ui/app/types/diff.ts
+++ b/polygerrit-ui/app/types/diff.ts
@@ -16,6 +16,7 @@
   DiffFileMetaInfo as DiffFileMetaInfoApi,
   DiffInfo as DiffInfoApi,
   DiffIntralineInfo,
+  DiffRangesToFocus,
   DiffResponsiveMode,
   DiffPreferencesInfo as DiffPreferenceInfoApi,
   IgnoreWhitespaceType,
@@ -27,6 +28,7 @@
 export type {
   ChangeType,
   DiffIntralineInfo,
+  DiffRangesToFocus,
   DiffResponsiveMode,
   IgnoreWhitespaceType,
   MarkLength,