Skip to content

Commit 91bd2dd

Browse files
authored
popped-lane-preview (#9805)
* Made details view pop Rearrange div structure to achieve an unfolded lane layout. The idea is to adjust the right margin and render the details view as an absolutely positioned element, allowing the scrollbar to be on the right side of the whole lane. Otherwise, the scrollbar would appear in the middle between sections, which doesn’t fit the layout. * Details view resizer refactoring Because we decided not to resize the commit/branch details section, and the changes preview section now takes only the maximum height of the remaining space or fits the content, basically only one section is resizable — the changes list. That’s why we don’t need complex calculations here.
1 parent 98c3267 commit 91bd2dd

File tree

4 files changed

+413
-371
lines changed

4 files changed

+413
-371
lines changed

apps/desktop/src/components/BranchList.svelte

Lines changed: 174 additions & 189 deletions
Original file line numberDiff line numberDiff line change
@@ -119,203 +119,194 @@
119119
const canPublishPR = $derived(forge.current.authenticated);
120120
</script>
121121

122-
<div class="wrapper">
123-
<div class="branches-wrapper">
124-
{#each branches as branch, i}
125-
{@const branchName = branch.name}
126-
{@const localAndRemoteCommits = stackService.commits(projectId, stackId, branchName)}
127-
{@const upstreamOnlyCommits = stackService.upstreamCommits(projectId, stackId, branchName)}
128-
{@const branchDetailsResult = stackService.branchDetails(projectId, stackId, branchName)}
129-
{@const commitResult = stackService.commitAt(projectId, stackId, branchName, 0)}
130-
{@const prResult = branch.prNumber
131-
? forge.current.prService?.get(branch.prNumber)
132-
: undefined}
122+
<div class="branches-wrapper">
123+
{#each branches as branch, i}
124+
{@const branchName = branch.name}
125+
{@const localAndRemoteCommits = stackService.commits(projectId, stackId, branchName)}
126+
{@const upstreamOnlyCommits = stackService.upstreamCommits(projectId, stackId, branchName)}
127+
{@const branchDetailsResult = stackService.branchDetails(projectId, stackId, branchName)}
128+
{@const commitResult = stackService.commitAt(projectId, stackId, branchName, 0)}
129+
{@const prResult = branch.prNumber ? forge.current.prService?.get(branch.prNumber) : undefined}
133130

134-
{@const first = i === 0}
131+
{@const first = i === 0}
135132

136-
<ReduxResult
137-
{projectId}
138-
{stackId}
139-
result={combineResults(
140-
localAndRemoteCommits.current,
141-
upstreamOnlyCommits.current,
142-
branchDetailsResult.current,
143-
commitResult.current
144-
)}
145-
>
146-
{#snippet children([localAndRemoteCommits, upstreamOnlyCommits, branchDetails, commit])}
147-
{@const firstBranch = i === 0}
148-
{@const lastBranch = i === branches.length - 1}
149-
{@const iconName = getIconFromCommitState(commit?.id, commit?.state)}
150-
{@const lineColor = commit
151-
? getColorFromCommitState(
152-
commit.state.type,
153-
commit.state.type === 'LocalAndRemote' && commit.id !== commit.state.subject
154-
)
155-
: 'var(--clr-commit-local)'}
156-
{@const isNewBranch =
157-
upstreamOnlyCommits.length === 0 && localAndRemoteCommits.length === 0}
158-
{@const selected =
159-
selection?.current?.branchName === branchName &&
160-
selection?.current.commitId === undefined}
161-
{@const pushStatus = branchDetails.pushStatus}
162-
{@const isConflicted = branchDetails.isConflicted}
163-
{@const lastUpdatedAt = branchDetails.lastUpdatedAt}
164-
{@const reviewId = branch.reviewId || undefined}
165-
{@const prNumber = branch.prNumber || undefined}
166-
<BranchCard
167-
type="stack-branch"
168-
{projectId}
169-
{stackId}
170-
{branchName}
171-
{lineColor}
172-
{first}
173-
{isCommitting}
174-
{iconName}
175-
{selected}
176-
{isNewBranch}
177-
{pushStatus}
178-
{isConflicted}
179-
{lastUpdatedAt}
180-
{reviewId}
181-
{prNumber}
182-
dropzones={[stackingReorderDropzoneManager.top(branchName)]}
183-
active={focusedStackId === stackId}
184-
trackingBranch={branch.remoteTrackingBranch ?? undefined}
185-
readonly={!!branch.remoteTrackingBranch}
186-
onclick={() => {
187-
uiState.stack(stackId).selection.set({ branchName });
188-
intelligentScrollingService.show(projectId, stackId, 'details');
189-
onselect?.();
190-
}}
191-
>
192-
{#snippet buttons()}
133+
<ReduxResult
134+
{projectId}
135+
{stackId}
136+
result={combineResults(
137+
localAndRemoteCommits.current,
138+
upstreamOnlyCommits.current,
139+
branchDetailsResult.current,
140+
commitResult.current
141+
)}
142+
>
143+
{#snippet children([localAndRemoteCommits, upstreamOnlyCommits, branchDetails, commit])}
144+
{@const firstBranch = i === 0}
145+
{@const lastBranch = i === branches.length - 1}
146+
{@const iconName = getIconFromCommitState(commit?.id, commit?.state)}
147+
{@const lineColor = commit
148+
? getColorFromCommitState(
149+
commit.state.type,
150+
commit.state.type === 'LocalAndRemote' && commit.id !== commit.state.subject
151+
)
152+
: 'var(--clr-commit-local)'}
153+
{@const isNewBranch =
154+
upstreamOnlyCommits.length === 0 && localAndRemoteCommits.length === 0}
155+
{@const selected =
156+
selection?.current?.branchName === branchName &&
157+
selection?.current.commitId === undefined}
158+
{@const pushStatus = branchDetails.pushStatus}
159+
{@const isConflicted = branchDetails.isConflicted}
160+
{@const lastUpdatedAt = branchDetails.lastUpdatedAt}
161+
{@const reviewId = branch.reviewId || undefined}
162+
{@const prNumber = branch.prNumber || undefined}
163+
<BranchCard
164+
type="stack-branch"
165+
{projectId}
166+
{stackId}
167+
{branchName}
168+
{lineColor}
169+
{first}
170+
{isCommitting}
171+
{iconName}
172+
{selected}
173+
{isNewBranch}
174+
{pushStatus}
175+
{isConflicted}
176+
{lastUpdatedAt}
177+
{reviewId}
178+
{prNumber}
179+
dropzones={[stackingReorderDropzoneManager.top(branchName)]}
180+
active={focusedStackId === stackId}
181+
trackingBranch={branch.remoteTrackingBranch ?? undefined}
182+
readonly={!!branch.remoteTrackingBranch}
183+
onclick={() => {
184+
uiState.stack(stackId).selection.set({ branchName });
185+
intelligentScrollingService.show(projectId, stackId, 'details');
186+
onselect?.();
187+
}}
188+
>
189+
{#snippet buttons()}
190+
<Button
191+
icon="new-empty-commit"
192+
size="tag"
193+
kind="outline"
194+
tooltip="Create empty commit"
195+
onclick={async () => {
196+
await insertBlankCommitInBranch({
197+
projectId,
198+
stackId,
199+
commitId: undefined,
200+
offset: -1
201+
});
202+
}}
203+
disabled={commitInsertion.current.isLoading}
204+
/>
205+
<Button
206+
icon="copy-small"
207+
size="tag"
208+
kind="outline"
209+
tooltip="Copy branch name"
210+
onclick={() => {
211+
copyToClipboard(branchName);
212+
}}
213+
/>
214+
{#if first}
193215
<Button
194-
icon="new-empty-commit"
216+
icon="new-dep-branch"
195217
size="tag"
196218
kind="outline"
197-
tooltip="Create empty commit"
219+
tooltip="Create new branch"
198220
onclick={async () => {
199-
await insertBlankCommitInBranch({
221+
addDependentBranchModalContext = {
200222
projectId,
201-
stackId,
202-
commitId: undefined,
203-
offset: -1
204-
});
205-
}}
206-
disabled={commitInsertion.current.isLoading}
207-
/>
208-
<Button
209-
icon="copy-small"
210-
size="tag"
211-
kind="outline"
212-
tooltip="Copy branch name"
213-
onclick={() => {
214-
copyToClipboard(branchName);
223+
stackId
224+
};
225+
226+
await tick();
227+
addDependentBranchModal?.show();
215228
}}
216229
/>
217-
{#if first}
230+
{/if}
231+
232+
{#if canPublishPR && !isNewBranch}
233+
{#if !branch.prNumber}
218234
<Button
219-
icon="new-dep-branch"
220235
size="tag"
221236
kind="outline"
222-
tooltip="Create new branch"
223-
onclick={async () => {
224-
addDependentBranchModalContext = {
225-
projectId,
226-
stackId
227-
};
228-
229-
await tick();
230-
addDependentBranchModal?.show();
237+
shrinkable
238+
onclick={(e) => {
239+
e.stopPropagation();
240+
projectState.exclusiveAction.set({
241+
type: 'create-pr',
242+
stackId,
243+
branchName
244+
});
231245
}}
232-
/>
233-
{/if}
234-
235-
{#if canPublishPR && !isNewBranch}
236-
{#if !branch.prNumber}
237-
<Button
238-
size="tag"
239-
kind="outline"
240-
shrinkable
241-
onclick={(e) => {
242-
e.stopPropagation();
243-
projectState.exclusiveAction.set({
244-
type: 'create-pr',
245-
stackId,
246-
branchName
247-
});
248-
}}
249-
testId={TestId.CreateReviewButton}
250-
disabled={!!projectState.exclusiveAction.current}
251-
icon={getForgeLogo(forge.current.name, true)}
252-
>
253-
{`Create ${forge.current.name === 'gitlab' ? 'MR' : 'PR'}`}
254-
</Button>
255-
{:else}
256-
{@const prUrl = prResult?.current.data?.htmlUrl}
257-
<Button
258-
size="tag"
259-
kind="outline"
260-
shrinkable
261-
disabled={!prUrl}
262-
onclick={() => {
263-
if (prUrl) {
264-
openExternalUrl(prUrl);
265-
}
266-
}}
267-
icon={forge.current.name === 'gitlab' ? 'view-mr-browser' : 'view-pr-browser'}
268-
>
269-
{`View ${forge.current.name === 'gitlab' ? 'MR' : 'PR'}`}
270-
</Button>
271-
{/if}
246+
testId={TestId.CreateReviewButton}
247+
disabled={!!projectState.exclusiveAction.current}
248+
icon={getForgeLogo(forge.current.name, true)}
249+
>
250+
{`Create ${forge.current.name === 'gitlab' ? 'MR' : 'PR'}`}
251+
</Button>
252+
{:else}
253+
{@const prUrl = prResult?.current.data?.htmlUrl}
254+
<Button
255+
size="tag"
256+
kind="outline"
257+
shrinkable
258+
disabled={!prUrl}
259+
onclick={() => {
260+
if (prUrl) {
261+
openExternalUrl(prUrl);
262+
}
263+
}}
264+
icon={forge.current.name === 'gitlab' ? 'view-mr-browser' : 'view-pr-browser'}
265+
>
266+
{`View ${forge.current.name === 'gitlab' ? 'MR' : 'PR'}`}
267+
</Button>
272268
{/if}
273-
<PushButton
274-
{branchName}
275-
{projectId}
276-
{stackId}
277-
multipleBranches={branches.length > 1}
278-
isFirstBranchInStack={firstBranch}
279-
isLastBranchInStack={lastBranch}
280-
/>
281-
{/snippet}
269+
{/if}
270+
<PushButton
271+
{branchName}
272+
{projectId}
273+
{stackId}
274+
multipleBranches={branches.length > 1}
275+
isFirstBranchInStack={firstBranch}
276+
isLastBranchInStack={lastBranch}
277+
/>
278+
{/snippet}
282279

283-
{#snippet menu({ rightClickTrigger })}
284-
{@const data = {
285-
branch,
286-
prNumber,
287-
first,
288-
stackLength: branches.length
289-
}}
290-
<BranchHeaderContextMenu
291-
{projectId}
292-
{stackId}
293-
{rightClickTrigger}
294-
contextData={data}
295-
/>
296-
{/snippet}
280+
{#snippet menu({ rightClickTrigger })}
281+
{@const data = {
282+
branch,
283+
prNumber,
284+
first,
285+
stackLength: branches.length
286+
}}
287+
<BranchHeaderContextMenu {projectId} {stackId} {rightClickTrigger} contextData={data} />
288+
{/snippet}
297289

298-
{#snippet branchContent()}
299-
<BranchCommitList
300-
{firstBranch}
301-
{lastBranch}
302-
active={focusedStackId === stackId}
303-
{projectId}
304-
{stackId}
305-
{branchName}
306-
{branchDetails}
307-
{stackingReorderDropzoneManager}
308-
{handleUncommit}
309-
{startEditingCommitMessage}
310-
{handleEditPatch}
311-
{onselect}
312-
/>
313-
{/snippet}
314-
</BranchCard>
315-
{/snippet}
316-
</ReduxResult>
317-
{/each}
318-
</div>
290+
{#snippet branchContent()}
291+
<BranchCommitList
292+
{firstBranch}
293+
{lastBranch}
294+
active={focusedStackId === stackId}
295+
{projectId}
296+
{stackId}
297+
{branchName}
298+
{branchDetails}
299+
{stackingReorderDropzoneManager}
300+
{handleUncommit}
301+
{startEditingCommitMessage}
302+
{handleEditPatch}
303+
{onselect}
304+
/>
305+
{/snippet}
306+
</BranchCard>
307+
{/snippet}
308+
</ReduxResult>
309+
{/each}
319310
</div>
320311

321312
<NewBranchModal {projectId} {stackId} bind:this={newBranchModal} />
@@ -355,16 +346,10 @@
355346
{/if}
356347

357348
<style lang="postcss">
358-
.wrapper {
359-
display: flex;
360-
flex-grow: 1;
361-
flex-direction: column;
362-
}
363-
364349
.branches-wrapper {
365350
display: flex;
366-
flex: 1;
351+
flex-grow: 1;
367352
flex-direction: column;
368-
padding: 12px;
353+
margin: 12px 0;
369354
}
370355
</style>

0 commit comments

Comments
 (0)