Skip to content

Commit bc3ffb7

Browse files
committed
feat: allow commits in new empty stacked branch
1 parent 26fbee1 commit bc3ffb7

File tree

6 files changed

+135
-68
lines changed

6 files changed

+135
-68
lines changed

apps/desktop/src/components/v3/BranchCommitList.svelte

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
stackId: string;
1414
branchName: string;
1515
lastBranch?: boolean;
16+
selectedBranchName?: string;
1617
selectedCommitId?: string;
1718
upstreamTemplate?: Snippet<
1819
[
@@ -28,16 +29,19 @@
2829
localAndRemoteTemplate?: Snippet<
2930
[{ commit: Commit; commitKey: CommitKey; first: boolean; last: boolean; selected: boolean }]
3031
>;
32+
emptyBranchCommitHere?: Snippet;
3133
}
3234
3335
let {
3436
projectId,
3537
stackId,
3638
branchName,
3739
lastBranch,
40+
selectedBranchName,
3841
selectedCommitId,
3942
localAndRemoteTemplate,
40-
upstreamTemplate
43+
upstreamTemplate,
44+
emptyBranchCommitHere
4145
}: Props = $props();
4246
4347
const [stackService] = inject(StackService);
@@ -53,7 +57,13 @@
5357
<ReduxResult result={combineResults(upstreamOnlyCommits, localAndRemoteCommits)}>
5458
{#snippet children([upstreamOnlyCommits, localAndRemoteCommits])}
5559
{#if !upstreamOnlyCommits.length && !localAndRemoteCommits.length}
56-
<EmptyBranch {lastBranch} />
60+
{#if selectedBranchName === branchName && emptyBranchCommitHere}
61+
<div class="empty-branch-commit-here">
62+
{@render emptyBranchCommitHere()}
63+
</div>
64+
{:else}
65+
<EmptyBranch {lastBranch} selected={selectedBranchName === branchName} />
66+
{/if}
5767
{:else}
5868
<div class="commit-list">
5969
{#if upstreamTemplate}
@@ -81,11 +91,11 @@
8191
</ReduxResult>
8292

8393
<style lang="postcss">
94+
.empty-branch-commit-here,
8495
.commit-list {
8596
position: relative;
8697
display: flex;
8798
flex-direction: column;
8899
border-radius: 0 0 var(--radius-ml) var(--radius-ml);
89-
/* overflow: hidden; */
90100
}
91101
</style>

apps/desktop/src/components/v3/BranchHeader.svelte

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,7 @@
9090

9191
<style lang="postcss">
9292
.branch-header {
93+
width: 100%;
9394
position: relative;
9495
display: flex;
9596
align-items: center;

apps/desktop/src/components/v3/CommitGoesHere.svelte

Lines changed: 83 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
import BranchCommitList from './BranchCommitList.svelte';
33
import BranchHeader from './BranchHeader.svelte';
44
import CommitRow from './CommitRow.svelte';
5+
import ScrollableContainer from '../ScrollableContainer.svelte';
56
import ReduxResult from '$components/ReduxResult.svelte';
67
import { BaseBranchService } from '$lib/baseBranch/baseBranchService';
78
import { createCommitPath } from '$lib/routes/routes.svelte';
@@ -35,77 +36,90 @@
3536
</div>
3637
</div>
3738
{/snippet}
38-
{#snippet commitHere(args: { commitId: string; last?: boolean })}
39+
40+
{#snippet commitHere(args: { commitId: string; last?: boolean; branchName: string })}
3941
<button
4042
class="commit-here"
4143
type="button"
4244
class:last={args.last}
43-
onclick={() => goto(createCommitPath(projectId, stackId, branchName, args.commitId))}
45+
onclick={() => goto(createCommitPath(projectId, stackId, args.branchName, args.commitId))}
4446
>
4547
<div class="commit-here__circle"></div>
4648
<div class="commit-here__line"></div>
4749
<div class="commit-here__label text-11 text-semibold">Commit here</div>
4850
</button>
4951
{/snippet}
50-
<div class="commit-goes-here">
51-
<ReduxResult result={branchesResult.current}>
52-
{#snippet children(branches)}
53-
{#each branches as branch, i}
54-
{@const lastBranch = i === branches.length - 1}
55-
<div class="branch" class:selected={branch.name === branchName}>
56-
<div class="header-wrapper">
57-
<BranchHeader
52+
53+
<ScrollableContainer>
54+
<div class="commit-goes-here">
55+
<ReduxResult result={branchesResult.current}>
56+
{#snippet children(branches)}
57+
{#each branches as branch, i}
58+
{@const lastBranch = i === branches.length - 1}
59+
<div class="branch" class:selected={branch.name === branchName}>
60+
<div class="header-wrapper">
61+
<BranchHeader
62+
{projectId}
63+
{stackId}
64+
{branch}
65+
onclick={() => {
66+
goto(createCommitPath(projectId, stackId, branch.name), {
67+
replaceState: true
68+
});
69+
}}
70+
isTopBranch={i === 0}
71+
lineColor="var(--clr-commit-local)"
72+
readonly
73+
/>
74+
</div>
75+
<BranchCommitList
5876
{projectId}
5977
{stackId}
60-
{branch}
61-
isTopBranch={i === 0}
62-
lineColor="var(--clr-commit-local)"
63-
readonly
64-
/>
65-
</div>
66-
<BranchCommitList
67-
{projectId}
68-
{stackId}
69-
branchName={branch.name}
70-
selectedCommitId={parentId}
71-
>
72-
{#snippet localAndRemoteTemplate({ commit, commitKey, first, last, selected })}
73-
{@const baseSha = $baseBranch?.baseSha}
74-
{#if selected}
75-
{@render indicator({ first })}
76-
{/if}
77-
<div class="commit-wrapper" class:last>
78-
{#if !selected}
79-
{@render commitHere({ commitId: commit.id })}
78+
branchName={branch.name}
79+
selectedBranchName={branchName}
80+
selectedCommitId={parentId}
81+
>
82+
{#snippet emptyBranchCommitHere()}
83+
{@render indicator({ first: true })}
84+
{/snippet}
85+
{#snippet localAndRemoteTemplate({ commit, commitKey, first, last, selected })}
86+
{@const baseSha = $baseBranch?.baseSha}
87+
{#if selected && branchName === branch.name}
88+
{@render indicator({ first })}
8089
{/if}
81-
<CommitRow
82-
{projectId}
83-
{commitKey}
84-
{first}
85-
{commit}
86-
lastCommit={last}
87-
lineColor="var(--clr-commit-local)"
88-
opacity={0.4}
89-
borderTop={selected}
90-
onclick={() =>
91-
goto(createCommitPath(projectId, stackId, branchName, commit.id), {
92-
replaceState: true
93-
})}
94-
/>
95-
{#if lastBranch && last && baseSha && parentId !== baseSha}
96-
{@render commitHere({ commitId: baseSha, last: true })}
90+
<div class="commit-wrapper" class:last>
91+
{#if !selected}
92+
{@render commitHere({ commitId: commit.id, branchName: branch.name })}
93+
{/if}
94+
<CommitRow
95+
{projectId}
96+
{commitKey}
97+
{first}
98+
{commit}
99+
lastCommit={last}
100+
lineColor="var(--clr-commit-local)"
101+
opacity={0.4}
102+
borderTop={selected}
103+
onclick={() =>
104+
goto(createCommitPath(projectId, stackId, branch.name, commit.id), {
105+
replaceState: true
106+
})}
107+
/>
108+
{#if lastBranch && last && baseSha && parentId !== baseSha}
109+
{@render commitHere({ commitId: baseSha, last: true, branchName: branch.name })}
110+
{/if}
111+
</div>
112+
{#if lastBranch && last && parentId === baseSha}
113+
{@render indicator({ last: true })}
97114
{/if}
98-
</div>
99-
{#if lastBranch && last && parentId === baseSha}
100-
{@render indicator({ last: true })}
101-
{/if}
102-
{/snippet}
103-
</BranchCommitList>
104-
</div>
105-
{/each}
106-
{/snippet}
107-
</ReduxResult>
108-
</div>
115+
{/snippet}
116+
</BranchCommitList>
117+
</div>
118+
{/each}
119+
{/snippet}
120+
</ReduxResult>
121+
</div>
122+
</ScrollableContainer>
109123

110124
<style lang="postcss">
111125
.commit-goes-here {
@@ -124,6 +138,11 @@
124138
background-color: var(--clr-bg-1);
125139
}
126140
}
141+
142+
.branch .empty-branch-commit-here .indicator {
143+
border-radius: 0 0 var(--radius-l) var(--radius-l);
144+
}
145+
127146
.header-wrapper {
128147
opacity: 0.4;
129148
}
@@ -142,6 +161,7 @@
142161
}
143162
&.last {
144163
border-bottom: none;
164+
border-radius: 0 0 var(--radius-l) var(--radius-l);
145165
}
146166
}
147167
.pin {
@@ -168,11 +188,16 @@
168188
display: flex;
169189
width: 100%;
170190
background-color: var(--clr-bg-2);
171-
&.last {
191+
192+
&.last:not(:has(~ .indicator)) {
172193
border-radius: 0 0 var(--radius-l) var(--radius-l);
173194
}
174195
}
175196
197+
.last .indicator {
198+
border-radius: 0 0 var(--radius-l) var(--radius-l);
199+
}
200+
176201
/* COMMIT HERE */
177202
.commit-here {
178203
width: 100%;

apps/desktop/src/components/v3/EmptyBranch.svelte

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,14 @@
33
44
interface Props {
55
lastBranch?: boolean;
6+
selected?: boolean;
67
}
78
8-
const { lastBranch }: Props = $props();
9+
const { lastBranch, selected }: Props = $props();
910
</script>
1011

1112
<div class="empty-series" style:--commit-color={getColorFromBranchType('LocalOnly')}>
12-
<div class="commit-line" class:dashed={lastBranch}></div>
13+
<div class="commit-line" class:selected class:dashed={lastBranch}></div>
1314
<div class="text-13 text-body empty-series__label">
1415
This is an empty branch.
1516
<br />
@@ -33,5 +34,10 @@
3334
.commit-line {
3435
position: absolute;
3536
left: 20px;
37+
opacity: 0.4;
38+
39+
&.selected {
40+
opacity: 1;
41+
}
3642
}
3743
</style>

apps/desktop/src/components/v3/NewCommit.svelte

Lines changed: 29 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -22,8 +22,10 @@
2222
};
2323
const { projectId, stackId, branchName, commitId }: Props = $props();
2424
25-
const baseBranchService = getContext(BaseBranchService);
2625
const stackService = getContext(StackService);
26+
const branchesResult = $derived(stackService.branches(projectId, stackId).current);
27+
const branches = $derived(branchesResult.data);
28+
const baseBranchService = getContext(BaseBranchService);
2729
const base = $derived(baseBranchService.base);
2830
2931
const changeSelection = getContext(ChangeSelectionService);
@@ -39,7 +41,30 @@
3941
4042
const baseSha = $derived($base?.baseSha);
4143
const defaultParentId = $derived(commit ? commit.id : baseSha);
42-
const parentId = $derived(commitId ? commitId : defaultParentId);
44+
45+
const parentId = $derived.by(() => {
46+
// If commitId is explicitly provided, use it
47+
if (commitId) return commitId;
48+
49+
// Try to find parent based on branch position in stack
50+
if (branches?.length) {
51+
const currentBranchIndex = branches.findIndex((b) => b.name === branchName);
52+
53+
// If this branch has a "parent" branch in the stack
54+
if (currentBranchIndex >= 0 && currentBranchIndex < branches.length - 1) {
55+
const parentBranch = branches[currentBranchIndex + 1];
56+
if (parentBranch?.name) {
57+
const parentCommit = stackService.commitAt(projectId, stackId, parentBranch.name, 0)
58+
.current.data;
59+
60+
if (parentCommit?.id) return parentCommit.id;
61+
}
62+
}
63+
}
64+
65+
// Fall back to default (either current commit or base SHA)
66+
return defaultParentId;
67+
});
4368
4469
/**
4570
* At the moment this code can only commit to the tip of the stack.
@@ -69,7 +94,7 @@
6994
stackId,
7095
parentId,
7196
message: message,
72-
stackSegmentShortName: "top",
97+
stackSegmentShortName: branchName,
7398
worktreeChanges: selection.map((item) =>
7499
item.type === 'full'
75100
? {
@@ -121,7 +146,7 @@
121146
background: var(--clr-bg-1);
122147
}
123148
.right {
124-
width: 300px;
149+
width: 310px;
125150
background-image: radial-gradient(
126151
oklch(from var(--clr-scale-ntrl-50) l c h / 0.5) 0.6px,
127152
#ffffff00 0.6px

apps/desktop/src/lib/stacks/stackService.svelte.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ type CreateCommitRequest = {
1414
stackId: string;
1515
message: string;
1616
parentId: string;
17-
stackSegmentShortName: string,
17+
stackSegmentShortName: string;
1818
worktreeChanges: {
1919
previousPathBytes?: number[];
2020
pathBytes: number[];

0 commit comments

Comments
 (0)