Skip to content

Commit 2fa1833

Browse files
authored
Merge pull request #27 from ruru-m07/ruru/feat/ability-to-make-commits
2 parents cb8d066 + 483372c commit 2fa1833

10 files changed

Lines changed: 429 additions & 290 deletions

File tree

apps/desktop/src-tauri/src/lib.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,14 +18,15 @@ pub fn run() {
1818
git::commands::get_status,
1919
git::commands::git_remove,
2020
git::commands::git_discard,
21-
git::commands::commit,
2221
git::diff::get_diff,
2322
git::branch::list_branch,
2423
git::branch::current_branch,
2524
git::branch::switch_branch,
2625
git::history::history,
2726
git::commit::last_commit,
2827
git::commit::commit_by_id,
28+
git::commit::create_commit,
29+
git::commit::create_empty_commit,
2930
git::origin::repository_origin,
3031
])
3132
.run(tauri::generate_context!())

apps/desktop/src/routes/app/git/index.tsx

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -139,10 +139,15 @@ const DiffArea = () => {
139139
options={{
140140
disableFileHeader: true,
141141
theme: { dark: "vesper", light: "vesper-light" },
142-
themeType: theme === "dark-classic" ? "dark" : "light",
142+
themeType: theme?.startsWith("dark-") ? "dark" : "light",
143143
diffStyle,
144144
overflow,
145145
lineDiffType,
146+
unsafeCSS: `
147+
pre {
148+
--diffs-light-bg: transparent !important;
149+
}
150+
`,
146151
}}
147152
/>
148153
) : null}

apps/desktop/src/routes/app/git/route.tsx

Lines changed: 104 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ import {
2222
DialogTitle,
2323
DialogTrigger,
2424
} from "@gitru/ui/components/dialog";
25+
import { Group, GroupSeparator } from "@gitru/ui/components/group";
2526
import { Input } from "@gitru/ui/components/input";
2627
import {
2728
InputGroup,
@@ -35,6 +36,10 @@ import {
3536
DropdownMenuContent,
3637
DropdownMenuItem,
3738
DropdownMenuTrigger,
39+
Menu,
40+
MenuItem,
41+
MenuPopup,
42+
MenuTrigger,
3843
} from "@gitru/ui/components/menu";
3944
import {
4045
ResizableHandle,
@@ -75,6 +80,7 @@ import {
7580
} from "lucide-react";
7681
import { memo, useCallback, useState } from "react";
7782
import { toast } from "sonner";
83+
import z from "zod";
7884
import { useDiffViewStore } from "@/components/diff/useDiffViewStore";
7985
import { useFileSelectionStore } from "@/components/diff/useFileSelectionStore";
8086
import { getStatusIcon } from "@/components/getStatusIcon";
@@ -85,6 +91,8 @@ import {
8591
} from "@/lib/time";
8692
import {
8793
getCommitHistory,
94+
useCreateCommit,
95+
useCurrentBranch,
8896
useRepositoryActions,
8997
useStatus,
9098
} from "@/state/hooks";
@@ -404,41 +412,7 @@ function GitPageLayout() {
404412
</>
405413
)}
406414
</div>
407-
<div className="shrink-0 border-l flex flex-col gap-2 justify-between items-center border-t px-2 py-2 bg-accent dark:bg-accent/10">
408-
<Input
409-
placeholder="Summary (required)"
410-
className="h-8 _border-border dark:bg-background!"
411-
/>
412-
<InputGroup className="dark:bg-background!">
413-
<InputGroupTextarea
414-
placeholder="Description"
415-
className="dark:bg-background!"
416-
/>
417-
<InputGroupAddon align="block-end">
418-
<Button
419-
variant="ghost"
420-
size="icon-xs"
421-
className="rounded-full opacity-50 hover:opacity-100"
422-
aria-label="Add Co Authors"
423-
>
424-
<UserPlus size={16} />
425-
</Button>
426-
<Separator
427-
orientation="vertical"
428-
className={"h-[80%] mx-0"}
429-
/>
430-
<Button
431-
variant="ghost"
432-
size="icon-xs"
433-
className="rounded-full opacity-50 hover:opacity-100"
434-
aria-label="Add files"
435-
>
436-
<Sparkles size={16} />
437-
</Button>
438-
</InputGroupAddon>
439-
</InputGroup>
440-
<Button className="w-full">Commit to main</Button>
441-
</div>
415+
<WriteCommitBox />
442416
</TabsPanel>
443417
<TabsPanel value="tab-2" className={"h-full"} tabIndex={-1}>
444418
<ScrollArea
@@ -918,3 +892,98 @@ const DiscardChangesDialog = memo(function DiscardChangesDialog({
918892
</Dialog>
919893
);
920894
});
895+
896+
const CoAuthers = z.array(z.tuple([z.string(), z.string()]));
897+
type CoAuthers = z.infer<typeof CoAuthers>;
898+
899+
const WriteCommitBox = memo(function WriteCommitBox() {
900+
const [title, setTitle] = useState("");
901+
const [description, setDescription] = useState("");
902+
const [co_authors, setCoAuthors] = useState<CoAuthers>([]);
903+
904+
const { data: currentBranch } = useCurrentBranch();
905+
const { mutateAsync: createCommit, isPending: isCreatingCommit } =
906+
useCreateCommit();
907+
908+
const handelCommit = useCallback(async () => {
909+
const data = await createCommit({
910+
title,
911+
description,
912+
co_authors,
913+
});
914+
if (data) {
915+
setTitle("");
916+
setDescription("");
917+
setCoAuthors([]);
918+
toast.success("Commit created successfully");
919+
}
920+
}, [createCommit, title, description, co_authors]);
921+
922+
return (
923+
<div>
924+
<div className="shrink-0 border-l flex flex-col gap-2 justify-between items-center border-t px-2 py-2 bg-accent dark:bg-accent/10">
925+
<Input
926+
placeholder="Summary (required)"
927+
className="h-8 _border-border dark:bg-background!"
928+
value={title}
929+
onChange={(e) => setTitle(e.target.value)}
930+
/>
931+
<InputGroup className="dark:bg-background!">
932+
<InputGroupTextarea
933+
placeholder="Description"
934+
className="dark:bg-background!"
935+
value={description}
936+
onChange={(e) => setDescription(e.target.value)}
937+
/>
938+
<InputGroupAddon align="block-end">
939+
<Button
940+
variant="ghost"
941+
size="icon-xs"
942+
className="rounded-full opacity-50 hover:opacity-100"
943+
aria-label="Add Co Authors"
944+
>
945+
<UserPlus size={16} />
946+
</Button>
947+
<Separator orientation="vertical" className={"h-4 mx-0"} />
948+
<Button
949+
variant="ghost"
950+
size="icon-xs"
951+
className="rounded-full opacity-50 hover:opacity-100"
952+
aria-label="Add files"
953+
>
954+
<Sparkles size={16} />
955+
</Button>
956+
</InputGroupAddon>
957+
</InputGroup>
958+
<Group aria-label="Subscription actions" className="w-full">
959+
<Button
960+
onClick={handelCommit}
961+
className="flex-1 truncate"
962+
disabled={isCreatingCommit || title.trim() === ""}
963+
>
964+
Commit to
965+
<span className="truncate -ml-1">{currentBranch?.name}</span>
966+
</Button>
967+
<GroupSeparator className="bg-primary/72" />
968+
<Menu>
969+
<MenuTrigger
970+
render={
971+
<Button
972+
aria-label="Copy options"
973+
size="icon"
974+
className="rounded-r-lg!"
975+
/>
976+
}
977+
>
978+
<ChevronDownIcon className="size-4" />
979+
</MenuTrigger>
980+
<MenuPopup align="end" className={"w-full"}>
981+
<MenuItem>Empty Commit</MenuItem>
982+
<MenuItem>Amend Last Commit</MenuItem>
983+
</MenuPopup>
984+
</Menu>
985+
</Group>
986+
</div>
987+
</div>
988+
);
989+
});

apps/desktop/src/state/domains/RepositoryState.ts

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
11
import { QueryClient } from "@tanstack/react-query";
22
import { invoke } from "@tauri-apps/api/core";
33
import {
4+
CreateCommitParams,
45
commitById,
6+
createCommit,
57
currentBranch,
68
getDiff,
79
getStatus,
@@ -243,6 +245,15 @@ class Commit extends StateDomain {
243245
return data;
244246
}
245247

248+
async createCommit(payload: CreateCommitParams["commitMeta"]) {
249+
const data = await createCommit({
250+
repoPath: this.repositoryPath,
251+
commitMeta: payload,
252+
});
253+
254+
return data;
255+
}
256+
246257
async history() {
247258
await this.queryClient.cancelQueries({
248259
queryKey: [...this.baseKey, "history"],

apps/desktop/src/state/hooks/useRepository.ts

Lines changed: 32 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,16 @@
1-
import { type UseQueryOptions, useQuery } from "@tanstack/react-query";
1+
import {
2+
type UseQueryOptions,
3+
useMutation,
4+
useQuery,
5+
} from "@tanstack/react-query";
26
import { useMemo } from "react";
3-
import type { Branch, GetDiffResponse, GetStatusResponse } from "@/tauri";
7+
import { toast } from "sonner";
8+
import type {
9+
Branch,
10+
CreateCommitParams,
11+
GetDiffResponse,
12+
GetStatusResponse,
13+
} from "@/tauri";
414
import { appState } from "../index";
515

616
type QueryOptions<T> = Omit<
@@ -208,6 +218,26 @@ export function getRepositoryOrigin() {
208218
});
209219
}
210220

221+
export function useCreateCommit() {
222+
const repo = appState.repository;
223+
224+
const mutation = useMutation({
225+
mutationFn: async (payload: CreateCommitParams["commitMeta"]) => {
226+
if (!repo) throw new Error("No repository selected");
227+
return await repo.commit.createCommit(payload);
228+
},
229+
onSuccess: async () => {
230+
await repo?.status.invalidate();
231+
await repo?.commit.invalidate();
232+
},
233+
onError: (error: string) => {
234+
toast.error(error);
235+
},
236+
});
237+
238+
return mutation;
239+
}
240+
211241
// ============================================
212242
// Action Hooks (for mutations)
213243
// ============================================

0 commit comments

Comments
 (0)