@@ -9,9 +9,11 @@ import type {DragHandler} from '../../DragHandle';
99import type { RenderGlyphResult } from '../../RenderDag' ;
1010import type { Dag } from '../../dag/dag' ;
1111import type { DagCommitInfo } from '../../dag/dagCommitInfo' ;
12+ import type { HashSet } from '../../dag/set' ;
1213import type { AbsorbEdit , AbsorbEditId } from '../absorb' ;
1314import type { CommitStackState , FileRev , FileStackIndex , CommitRev } from '../commitStackState' ;
1415import type { Map as ImMap } from 'immutable' ;
16+ import type { ReactNode } from 'react' ;
1517
1618import { FileHeader , IconType } from '../../ComparisonView/SplitDiffView/SplitDiffFileHeader' ;
1719import { ScrollY } from '../../ComponentUtils' ;
@@ -27,6 +29,7 @@ import * as stylex from '@stylexjs/stylex';
2729import { Column , Row } from 'isl-components/Flex' ;
2830import { Icon } from 'isl-components/Icon' ;
2931import { atom , useAtomValue } from 'jotai' ;
32+ import React from 'react' ;
3033import { nullthrows } from 'shared/utils' ;
3134
3235const styles = stylex . create ( {
@@ -102,6 +105,9 @@ const styles = stylex.create({
102105 instruction : {
103106 padding : 'var(--halfpad) var(--pad)' ,
104107 } ,
108+ inlineIcon : {
109+ verticalAlign : 'bottom' ,
110+ } ,
105111 scrollYPadding : {
106112 paddingRight : 'var(--pad)' ,
107113 } ,
@@ -120,18 +126,7 @@ export function AbsorbStackEditPanel() {
120126 return (
121127 < >
122128 < Column >
123- < div { ...stylex . props ( styles . instruction ) } >
124- < Row >
125- < Icon icon = "info" />
126- < div >
127- < T > Drag a diff chunk to a commit to amend the diff chunk into the commit.</ T >
128- < br />
129- < T > Diff chunks under "You are here" will be left in the working copy.</ T >
130- < br />
131- < T > Only commits that modify related files are shown.</ T >
132- </ div >
133- </ Row >
134- </ div >
129+ < AbsorbInstruction dag = { dag } subset = { subset } />
135130 < ScrollY maxSize = "calc(100vh - 200px)" { ...stylex . props ( styles . scrollYPadding ) } >
136131 < RenderDag
137132 className = "absorb-dag"
@@ -152,6 +147,45 @@ export function AbsorbStackEditPanel() {
152147 ) ;
153148}
154149
150+ function AbsorbInstruction ( props : { subset : HashSet ; dag : Dag } ) {
151+ const { dag, subset} = props ;
152+ const hasOmittedCommits = subset . size < dag . all ( ) . size ;
153+ const hasDndDestinations = subset . intersect ( dag . draft ( ) ) . size > 1 ;
154+ const tips : ReactNode [ ] = [ ] ;
155+ if ( hasDndDestinations ) {
156+ tips . push ( < T > Diff chunks under a commit will be amended to the commit.</ T > ) ;
157+ }
158+ tips . push ( < T > Diff chunks under "You are here" will be left in the working copy.</ T > ) ;
159+ if ( hasDndDestinations ) {
160+ tips . push (
161+ < T
162+ replace = { { $grabber : < Icon icon = "grabber" size = "S" { ...stylex . props ( styles . inlineIcon ) } /> } } >
163+ Commits are pre-selected based on blame information. Drag $grabber to adjust.
164+ </ T > ,
165+ ) ;
166+ if ( hasOmittedCommits ) {
167+ tips . push ( < T > Only commits that modify related files/areas are shown.</ T > ) ;
168+ }
169+ } else {
170+ tips . push ( < T > Nothing to absorb. The commit stack did not modify relevant files.</ T > ) ;
171+ }
172+ return (
173+ < div { ...stylex . props ( styles . instruction ) } >
174+ < Row >
175+ < Icon icon = "info" />
176+ < div >
177+ { tips . map ( ( tip , idx ) => (
178+ < React . Fragment key = { idx } >
179+ { idx > 0 && < br /> }
180+ { tip }
181+ </ React . Fragment >
182+ ) ) }
183+ </ div >
184+ </ Row >
185+ </ div >
186+ ) ;
187+ }
188+
155189const candidateDropTargetRevs = atom < readonly CommitRev [ ] | undefined > ( get => {
156190 const edit = get ( draggingAbsorbEdit ) ;
157191 const stack = get ( stackEditStack ) ;
0 commit comments