Skip to content

Commit 1467fb7

Browse files
committed
Add absorb operation mode
1 parent 39e448f commit 1467fb7

13 files changed

Lines changed: 107 additions & 201 deletions

File tree

apps/lite/package.json

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -130,7 +130,6 @@
130130
"electron-updater": "^6.8.4",
131131
"react": "^19.2.4",
132132
"react-dom": "^19.2.4",
133-
"react-error-boundary": "^6.0.0",
134133
"react-redux": "^9.2.0",
135134
"react-resizable-panels": "^4.7.3"
136135
},

apps/lite/ui/src/operations/operation.ts

Lines changed: 28 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,10 +23,11 @@ import {
2323
commitSquashMutationOptions,
2424
commitUncommitChangesMutationOptions,
2525
commitUncommitMutationOptions,
26+
absorbMutationOptions,
2627
moveBranchMutationOptions,
2728
tearOffBranchMutationOptions,
2829
} from "#ui/api/mutations.ts";
29-
import { InsertSide, RelativeTo } from "@gitbutler/but-sdk";
30+
import { CommitAbsorption, InsertSide, RelativeTo } from "@gitbutler/but-sdk";
3031
import { Operand, operandEquals, operandFileParent } from "#ui/operands.ts";
3132
import { resolveDiffSpecs } from "#ui/operations/diff-specs.ts";
3233
import { decodeRefName } from "#ui/api/ref-name.ts";
@@ -67,8 +68,13 @@ export type CommitUncommitChangesOperation = Omit<
6768
export type MoveBranchOperation = Omit<MoveBranchParams, "dryRun" | "projectId">;
6869
/** @public */
6970
export type TearOffBranchOperation = Omit<TearOffBranchParams, "dryRun" | "projectId">;
71+
/** @public */
72+
export type AbsorbOperation = {
73+
absorptionPlan: Array<CommitAbsorption>;
74+
};
7075

7176
export type Operation =
77+
| ({ _tag: "Absorb" } & AbsorbOperation)
7278
| ({ _tag: "CommitAmend" } & CommitAmendOperation)
7379
| ({ _tag: "CommitCreate" } & CommitCreateOperation)
7480
| ({ _tag: "CommitCreateFromCommittedChanges" } & CommitCreateFromCommittedChangesOperation)
@@ -80,6 +86,12 @@ export type Operation =
8086
| ({ _tag: "MoveBranch" } & MoveBranchOperation)
8187
| ({ _tag: "TearOffBranch" } & TearOffBranchOperation);
8288

89+
/** @public */
90+
export const absorbOperation = (operation: AbsorbOperation): Operation => ({
91+
_tag: "Absorb",
92+
...operation,
93+
});
94+
8395
/** @public */
8496
export const commitAmendOperation = (operation: CommitAmendOperation): Operation => ({
8597
_tag: "CommitAmend",
@@ -149,6 +161,7 @@ export const tearOffBranchOperation = (operation: TearOffBranchOperation): Opera
149161
export const operationLabel = (operation: Operation): string =>
150162
Match.value(operation).pipe(
151163
Match.tagsExhaustive({
164+
Absorb: () => "Absorb",
152165
CommitAmend: () => "Amend",
153166
CommitCreate: ({ side }) =>
154167
Match.value(side).pipe(
@@ -216,10 +229,24 @@ export const useRunOperation = () => {
216229
const commitUncommitChanges = useMutation(commitUncommitChangesMutationOptions);
217230
const moveBranch = useMutation(moveBranchMutationOptions);
218231
const tearOffBranch = useMutation(tearOffBranchMutationOptions);
232+
const absorb = useMutation({
233+
...absorbMutationOptions,
234+
onSuccess: async (response, input, context, mutation) => {
235+
await absorbMutationOptions.onSuccess?.(response, input, context, mutation);
236+
237+
toastManager.add({ title: "Changes absorbed successfully" });
238+
},
239+
});
219240

220241
return (projectId: string, operation: Operation): void => {
221242
Match.value(operation).pipe(
222243
Match.tagsExhaustive({
244+
Absorb: (operation) => {
245+
absorb.mutate({
246+
projectId,
247+
absorptionPlan: operation.absorptionPlan,
248+
});
249+
},
223250
CommitAmend: (operation) => {
224251
const changes = resolveDiffSpecs({
225252
source: operation.source,

apps/lite/ui/src/outline/mode.ts

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,13 @@ import {
1010
} from "#ui/operands.ts";
1111
import { getOperation, getOperations, OperationType } from "#ui/operations/operation.ts";
1212
import { filterNavigationIndex, NavigationIndex } from "#ui/workspace/navigation-index.ts";
13+
import { CommitAbsorption } from "@gitbutler/but-sdk";
1314

15+
/** @public */
16+
export type AbsorbOperationMode = {
17+
source: Operand;
18+
absorptionPlan: Array<CommitAbsorption>;
19+
};
1420
/** @public */
1521
export type RubOperationMode = { source: Operand };
1622
/** @public */
@@ -20,11 +26,22 @@ export type MoveOperationMode = { source: Operand };
2026
/** @public */
2127
export type DragAndDropOperationMode = { source: Operand; operationType: OperationType | null };
2228
export type OperationMode =
29+
| ({ _tag: "Absorb" } & AbsorbOperationMode)
2330
| ({ _tag: "Rub" } & RubOperationMode)
2431
| ({ _tag: "Cut" } & CutOperationMode)
2532
| ({ _tag: "Move" } & MoveOperationMode)
2633
| ({ _tag: "DragAndDrop" } & DragAndDropOperationMode);
2734

35+
/** @public */
36+
export const absorbOperationMode = ({
37+
source,
38+
absorptionPlan,
39+
}: AbsorbOperationMode): OperationMode => ({
40+
_tag: "Absorb",
41+
source,
42+
absorptionPlan,
43+
});
44+
2845
/** @public */
2946
export const rubOperationMode = ({ source }: RubOperationMode): OperationMode => ({
3047
_tag: "Rub",
@@ -97,6 +114,7 @@ export const operationModeToOperationType = (operationMode: OperationMode): Oper
97114
Match.value(operationMode).pipe(
98115
Match.withReturnType<OperationType | null>(),
99116
Match.tags({
117+
Absorb: () => null,
100118
Rub: () => "rub",
101119
Cut: () => null,
102120
// We should have the ability to move either above or below.
@@ -136,6 +154,10 @@ const operationModeHasOperation = ({
136154
}): boolean =>
137155
Match.value(mode).pipe(
138156
Match.tagsExhaustive({
157+
Absorb: ({ absorptionPlan }) =>
158+
absorptionPlan.some(({ stackId, commitId }) =>
159+
operandEquals(commitOperand({ stackId, commitId }), operand),
160+
),
139161
DragAndDrop: ({ source }) => hasAnyOperation(source, operand),
140162
Cut: ({ source }) => hasAnyOperation(source, operand),
141163
Move: (mode) =>
@@ -168,6 +190,10 @@ export const filterNavigationIndexForOutlineMode = ({
168190
navigationIndexUnfiltered,
169191
(operand) =>
170192
operandContains(operand, operationMode.source) ||
193+
(operationMode._tag === "Absorb" &&
194+
operationMode.absorptionPlan.some(({ stackId, commitId }) =>
195+
operandEquals(commitOperand({ stackId, commitId }), operand),
196+
)) ||
171197
operationModeHasOperation({ mode: operationMode, operand }),
172198
),
173199
RenameBranch: (x) =>

apps/lite/ui/src/projects/state.ts

Lines changed: 13 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,13 @@
11
import { createSlice, type PayloadAction } from "@reduxjs/toolkit";
22
import type { RootState } from "#ui/store.ts";
3-
import { type AbsorptionTarget } from "@gitbutler/but-sdk";
3+
import { type CommitAbsorption } from "@gitbutler/but-sdk";
44
import { type BranchOperand, type CommitOperand, type Operand } from "#ui/operands.ts";
55
import { type Panel } from "#ui/panels.ts";
66
import * as panels from "#ui/panels/state.ts";
77
import * as workspace from "#ui/projects/workspace/state.ts";
88
import { OperationType } from "#ui/operations/operation.ts";
99

1010
type Dialog =
11-
| { _tag: "Absorption"; target: AbsorptionTarget }
1211
| { _tag: "None" }
1312
| { _tag: "ApplyBranchPicker" }
1413
| { _tag: "BranchPicker" }
@@ -89,6 +88,18 @@ const projectSlice = createSlice({
8988
const projectState = ensureProjectState(state, projectId);
9089
workspace.enterCutMode(projectState.workspace, source);
9190
},
91+
enterAbsorbMode: (
92+
state,
93+
action: PayloadAction<{
94+
projectId: string;
95+
source: Operand;
96+
absorptionPlan: Array<CommitAbsorption>;
97+
}>,
98+
) => {
99+
const { projectId, source, absorptionPlan } = action.payload;
100+
const projectState = ensureProjectState(state, projectId);
101+
workspace.enterAbsorbMode(projectState.workspace, source, absorptionPlan);
102+
},
92103
enterMoveMode: (state, action: PayloadAction<{ projectId: string; source: Operand }>) => {
93104
const { projectId, source } = action.payload;
94105
const projectState = ensureProjectState(state, projectId);
@@ -167,16 +178,6 @@ const projectSlice = createSlice({
167178
_tag: "ApplyBranchPicker",
168179
};
169180
},
170-
openAbsorptionDialog: (
171-
state,
172-
action: PayloadAction<{ projectId: string; target: AbsorptionTarget }>,
173-
) => {
174-
const { projectId, target } = action.payload;
175-
ensureProjectState(state, projectId).dialog = {
176-
_tag: "Absorption",
177-
target,
178-
};
179-
},
180181
closeDialog: (state, action: PayloadAction<{ projectId: string }>) => {
181182
ensureProjectState(state, action.payload.projectId).dialog = { _tag: "None" };
182183
},

apps/lite/ui/src/projects/workspace/state.ts

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import { OperationType } from "#ui/operations/operation.ts";
2+
import { CommitAbsorption } from "@gitbutler/but-sdk";
23
import { Match } from "effect";
34
import {
45
branchOperand,
@@ -9,6 +10,7 @@ import {
910
type Operand,
1011
} from "#ui/operands.ts";
1112
import {
13+
absorbOperationMode,
1214
cutOperationMode,
1315
defaultOutlineMode,
1416
dragAndDropOperationMode,
@@ -60,6 +62,14 @@ export const enterCutMode = (state: WorkspaceState, source: Operand) => {
6062
state.mode = operationOutlineMode(cutOperationMode({ source }));
6163
};
6264

65+
export const enterAbsorbMode = (
66+
state: WorkspaceState,
67+
source: Operand,
68+
absorptionPlan: Array<CommitAbsorption>,
69+
) => {
70+
state.mode = operationOutlineMode(absorbOperationMode({ source, absorptionPlan }));
71+
};
72+
6373
export const enterDragAndDropMode = (state: WorkspaceState, source: Operand) => {
6474
state.mode = operationOutlineMode(dragAndDropOperationMode({ source, operationType: null }));
6575
};

apps/lite/ui/src/routes/project/$id/workspace/AbsorptionDialog.module.css

Lines changed: 0 additions & 11 deletions
This file was deleted.

apps/lite/ui/src/routes/project/$id/workspace/AbsorptionDialog.tsx

Lines changed: 0 additions & 136 deletions
This file was deleted.

0 commit comments

Comments
 (0)