Skip to content

Commit cd3b3c7

Browse files
authored
Merge pull request #13115 from gitbutlerapp/push-sounqutuskvo
Lite: add ability to absorb changes
2 parents c74b01d + 8ce7d42 commit cd3b3c7

14 files changed

Lines changed: 385 additions & 35 deletions

File tree

apps/lite/electron/src/ipc.ts

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,10 @@
11
import type {
2+
AbsorptionTarget,
23
ApplyOutcome,
34
BranchDetails,
45
BranchListing,
56
BranchListingFilter,
7+
CommitAbsorption,
68
HunkAssignmentRequest,
79
CommitDetails,
810
DiffSpec,
@@ -115,6 +117,16 @@ export interface CommitUncommitChangesParams {
115117
assignTo: string | null;
116118
}
117119

120+
export interface AbsorptionPlanParams {
121+
projectId: string;
122+
target: AbsorptionTarget;
123+
}
124+
125+
export interface AbsorbParams {
126+
projectId: string;
127+
absorptionPlan: Array<CommitAbsorption>;
128+
}
129+
118130
export interface TreeChangeDiffParams {
119131
projectId: string;
120132
change: TreeChange;
@@ -145,6 +157,8 @@ export interface WatcherSubscribeResult {
145157
}
146158

147159
export interface LiteElectronApi {
160+
absorptionPlan: (params: AbsorptionPlanParams) => Promise<Array<CommitAbsorption>>;
161+
absorb: (params: AbsorbParams) => Promise<number>;
148162
apply: (params: ApplyParams) => Promise<ApplyOutcome>;
149163
assignHunk: (params: AssignHunkParams) => Promise<void>;
150164
branchDetails: (params: BranchDetailsParams) => Promise<BranchDetails>;
@@ -180,6 +194,8 @@ export interface LiteElectronApi {
180194
}
181195

182196
export const liteIpcChannels = {
197+
absorptionPlan: "workspace:absorption-plan",
198+
absorb: "workspace:absorb",
183199
apply: "workspace:apply",
184200
assignHunk: "workspace:assign-hunk",
185201
branchDetails: "workspace:branch-details",

apps/lite/electron/src/main.ts

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
import WatcherManager from "./watcher.js";
22
import {
33
liteIpcChannels,
4+
type AbsorbParams,
5+
type AbsorptionPlanParams,
46
type AssignHunkParams,
57
type BranchDetailsParams,
68
type BranchDiffParams,
@@ -23,6 +25,8 @@ import {
2325
WatcherUnsubscribeParams,
2426
} from "./ipc.js";
2527
import {
28+
absorb,
29+
absorptionPlan,
2630
apply,
2731
assignHunk,
2832
branchDetails,
@@ -56,6 +60,13 @@ const currentFilePath = fileURLToPath(import.meta.url);
5660
const currentDirPath = path.dirname(currentFilePath);
5761

5862
function registerIpcHandlers(): void {
63+
ipcMain.handle(
64+
liteIpcChannels.absorptionPlan,
65+
(_e, { projectId, target }: AbsorptionPlanParams) => absorptionPlan(projectId, target),
66+
);
67+
ipcMain.handle(liteIpcChannels.absorb, (_e, { projectId, absorptionPlan }: AbsorbParams) =>
68+
absorb(projectId, absorptionPlan),
69+
);
5970
ipcMain.handle(liteIpcChannels.apply, (_e, { projectId, existingBranch }: ApplyParams) =>
6071
apply(projectId, existingBranch),
6172
);

apps/lite/electron/src/preload.cts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import { contextBridge, ipcRenderer } from "electron";
22
import type { LiteElectronApi, WatcherSubscribeResult } from "./ipc";
33
import type {
4+
CommitAbsorption,
45
ApplyOutcome,
56
BranchDetails,
67
BranchListing,
@@ -35,6 +36,9 @@ const watcherListenerBySubscription = new Map<
3536
>();
3637

3738
const api: LiteElectronApi = {
39+
absorptionPlan: (params) =>
40+
ipcRenderer.invoke("workspace:absorption-plan", params) as Promise<Array<CommitAbsorption>>,
41+
absorb: (params) => ipcRenderer.invoke("workspace:absorb", params) as Promise<number>,
3842
apply: (params) => ipcRenderer.invoke("workspace:apply", params) as Promise<ApplyOutcome>,
3943
assignHunk: (params) => ipcRenderer.invoke("workspace:assign-hunk", params) as Promise<void>,
4044
branchDetails: (params) =>

apps/lite/ui/src/ShortcutButton.tsx

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

apps/lite/ui/src/api/mutations.ts

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,17 @@ export const applyBranchMutationOptions = mutationOptions({
88
},
99
});
1010

11+
export const absorptionPlanMutationOptions = mutationOptions({
12+
mutationFn: window.lite.absorptionPlan,
13+
});
14+
15+
export const absorbMutationOptions = mutationOptions({
16+
mutationFn: window.lite.absorb,
17+
onSuccess: async (_data, _input, _ctx, { client }) => {
18+
await client.invalidateQueries();
19+
},
20+
});
21+
1122
export const commitInsertBlankMutationOptions = mutationOptions({
1223
mutationFn: window.lite.commitInsertBlank,
1324
onSuccess: async (_data, _input, _ctx, { client }) => {

apps/lite/ui/src/components/icons.tsx

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,16 @@ export const ArrowUpIcon: FC<ComponentProps<"svg">> = (props) => (
7777
</svg>
7878
);
7979

80+
export const AbsorbIcon: FC<ComponentProps<"svg">> = (props) => (
81+
<svg aria-hidden="true" width="16" height="16" viewBox="0 0 16 16" {...props}>
82+
<path
83+
d="M8 3.55c0 .98-.68 1.84-1.37 2.74-.74.96-1.5 1.95-1.5 3.16a2.87 2.87 0 1 0 5.74 0c0-1.21-.76-2.2-1.5-3.16C8.68 5.39 8 4.53 8 3.55Z"
84+
fill="currentColor"
85+
stroke="none"
86+
/>
87+
</svg>
88+
);
89+
8090
export const MenuTriggerIcon: FC = () => (
8191
<svg aria-hidden="true" width="16" height="16" viewBox="0 0 16 16">
8292
<circle cx="4" cy="8" r="1.25" fill="currentColor" />

apps/lite/ui/src/routes/__root.tsx

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,8 @@ import { QueryClient } from "@tanstack/react-query";
55
import { createRootRouteWithContext } from "@tanstack/react-router";
66
import { useFullscreenPreview } from "../hooks/useFullscreenPreview";
77
import { usePreviewPanel } from "../hooks/usePreviewPanel";
8-
import { ShortcutButton } from "#ui/ShortcutButton.tsx";
98
import { ShortcutsBarPortalContext } from "#ui/routes/project/$id/-ShortcutsBar.tsx";
9+
import { bindingButtonLabel } from "#ui/shortcuts.ts";
1010
import {
1111
openFullscreenPreviewBinding,
1212
togglePreviewBinding,
@@ -98,17 +98,21 @@ const TopBarActions: FC<{
9898

9999
return (
100100
<div className={styles.topBarActions}>
101-
<ShortcutButton
102-
binding={togglePreviewBinding}
101+
<button
102+
type="button"
103103
className={uiStyles.button}
104104
aria-pressed={previewPanel}
105105
onClick={() => setPreviewPanel((visible) => !visible)}
106-
/>
107-
<ShortcutButton
108-
binding={openFullscreenPreviewBinding}
106+
>
107+
{bindingButtonLabel(togglePreviewBinding)}
108+
</button>
109+
<button
110+
type="button"
109111
className={uiStyles.button}
110112
onClick={() => setShowFullscreenPreview(true)}
111-
/>
113+
>
114+
{bindingButtonLabel(openFullscreenPreviewBinding)}
115+
</button>
112116
</div>
113117
);
114118
};

apps/lite/ui/src/routes/project/$id/-ProjectPreviewLayout.tsx

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11
import { Dialog } from "@base-ui/react";
22
import { FC, ReactNode, use, useState } from "react";
33
import { Group, Panel, Separator, useDefaultLayout } from "react-resizable-panels";
4-
import { ShortcutButton } from "#ui/ShortcutButton.tsx";
54
import { ShortcutsBarPortalContext } from "#ui/routes/project/$id/-ShortcutsBar.tsx";
65
import { useFullscreenPreview } from "#ui/hooks/useFullscreenPreview.ts";
76
import { usePreviewPanel } from "#ui/hooks/usePreviewPanel.ts";
7+
import { bindingButtonLabel } from "#ui/shortcuts.ts";
88
import uiStyles from "#ui/ui.module.css";
99
import { closeFullscreenPreviewBinding } from "./workspace/-WorkspaceShortcuts.ts";
1010
import sharedStyles from "./-shared.module.css";
@@ -58,11 +58,13 @@ export const ProjectPreviewLayout: FC<{
5858
<Dialog.Portal>
5959
<Dialog.Popup aria-label="Preview" className={sharedStyles.previewDialogPopup}>
6060
<div className={sharedStyles.previewDialogBody}>
61-
<ShortcutButton
62-
binding={closeFullscreenPreviewBinding}
61+
<button
62+
type="button"
6363
className={uiStyles.button}
6464
onClick={() => setShowFullscreenPreview(false)}
65-
/>
65+
>
66+
{bindingButtonLabel(closeFullscreenPreviewBinding)}
67+
</button>
6668
{preview}
6769
</div>
6870
<footer ref={setDialogShortcutsBarPortalNode} />

apps/lite/ui/src/routes/project/$id/-shared.tsx

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,8 @@ const hunkHeaderEquals = (a: HunkHeader, b: HunkHeader): boolean =>
4343
export const formatHunkHeader = (hunk: HunkHeader): string =>
4444
`-${hunk.oldStart},${hunk.oldLines} +${hunk.newStart},${hunk.newLines}`;
4545

46+
export const shortCommitId = (commitId: string): string => commitId.slice(0, 7);
47+
4648
const assignedHunks = (
4749
hunks: Array<DiffHunk>,
4850
assignments: Array<HunkAssignment>,
@@ -196,11 +198,17 @@ export const CommitDetails: FC<{
196198
);
197199
};
198200

201+
export const commitTitle = (message: string): string => {
202+
const _title = message.trim().split("\n")[0];
203+
const title = _title === "" ? undefined : _title;
204+
return title ?? "(no message)";
205+
};
206+
199207
export const CommitLabel: FC<{
200208
commit: Commit;
201209
}> = ({ commit }) => (
202210
<>
203-
{commit.message === "" ? <>(no message)</> : commit.message.split("\n")[0]}
211+
{commitTitle(commit.message)}
204212
{commit.hasConflicts && " ⚠️"}
205213
</>
206214
);
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
.backdrop {
2+
position: fixed;
3+
inset: 0;
4+
background-color: rgb(0 0 0 / 0.35);
5+
}
6+
7+
.popup {
8+
display: flex;
9+
position: fixed;
10+
top: 50%;
11+
left: 50%;
12+
row-gap: 12px;
13+
flex-direction: column;
14+
padding: 16px;
15+
transform: translate(-50%, -50%);
16+
border: 1px solid;
17+
background-color: white;
18+
}
19+
20+
.body {
21+
display: flex;
22+
row-gap: 8px;
23+
flex-direction: column;
24+
}
25+
26+
.actions {
27+
display: flex;
28+
column-gap: 8px;
29+
justify-content: end;
30+
}

0 commit comments

Comments
 (0)