mirror of
https://github.com/getpaseo/paseo.git
synced 2026-10-23 17:52:49 +00:00
* feat(git): default review to all branch changes Keep the selected comparison stable while agents edit and commit so reviewing the complete result does not require switching scopes or interrupt unfinished comments. * test(git): release Windows checkout handles during cleanup Allow transient filesystem handles from subscription teardown to close before removing the test repository.
162 lines
4.2 KiB
TypeScript
162 lines
4.2 KiB
TypeScript
import { useCallback, useEffect, useMemo } from "react";
|
|
import {
|
|
buildWorkspaceAttachmentScopeKey,
|
|
useWorkspaceAttachmentsStore,
|
|
} from "@/attachments/workspace-attachments-store";
|
|
import {
|
|
buildReviewDraftKey,
|
|
useInlineReviewController,
|
|
useReviewAttachmentSnapshot,
|
|
useReviewFeedback,
|
|
} from "@/review";
|
|
import { useCheckoutDiffQuery } from "@/git/use-diff-query";
|
|
import { useCheckoutStatusQuery } from "@/git/use-status-query";
|
|
import { useWorkingDiffComparison } from "@/git/working-diff-comparison";
|
|
|
|
interface UseWorkingDiffOptions {
|
|
serverId: string;
|
|
workspaceId?: string;
|
|
cwd: string;
|
|
ignoreWhitespace: boolean;
|
|
enabled: boolean;
|
|
queryScope?: string;
|
|
presentation?: string;
|
|
}
|
|
|
|
export function useWorkingDiff({
|
|
serverId,
|
|
workspaceId,
|
|
cwd,
|
|
ignoreWhitespace,
|
|
enabled,
|
|
queryScope,
|
|
presentation,
|
|
}: UseWorkingDiffOptions) {
|
|
const {
|
|
status,
|
|
isLoading: isStatusLoading,
|
|
isError: isStatusError,
|
|
error: statusError,
|
|
} = useCheckoutStatusQuery({ serverId, cwd });
|
|
const gitStatus = status && status.isGit ? status : null;
|
|
const isGit = Boolean(gitStatus);
|
|
const notGit = status !== null && !status.isGit && !status.error;
|
|
const statusErrorMessage =
|
|
status?.error?.message ??
|
|
(isStatusError && statusError instanceof Error ? statusError.message : null);
|
|
const baseRef = gitStatus?.baseRef ?? undefined;
|
|
const currentBranchName =
|
|
gitStatus?.currentBranch && gitStatus.currentBranch !== "HEAD" ? gitStatus.currentBranch : null;
|
|
|
|
const { comparison: diffMode, selectComparison } = useWorkingDiffComparison({
|
|
serverId,
|
|
workspaceId,
|
|
cwd,
|
|
});
|
|
const selectUncommitted = useCallback(() => selectComparison("uncommitted"), [selectComparison]);
|
|
const selectAll = useCallback(() => selectComparison("all"), [selectComparison]);
|
|
const selectBase = useCallback(() => selectComparison("base"), [selectComparison]);
|
|
|
|
const {
|
|
files,
|
|
payloadError: diffPayloadError,
|
|
diffTooLarge,
|
|
isLoading: isDiffLoading,
|
|
} = useCheckoutDiffQuery({
|
|
serverId,
|
|
cwd,
|
|
mode: diffMode,
|
|
baseRef,
|
|
ignoreWhitespace,
|
|
enabled: enabled && isGit,
|
|
queryScope,
|
|
});
|
|
const reviewDraftKey = useMemo(
|
|
() =>
|
|
buildReviewDraftKey({
|
|
serverId,
|
|
workspaceId,
|
|
cwd,
|
|
mode: diffMode,
|
|
baseRef,
|
|
ignoreWhitespace,
|
|
}),
|
|
[baseRef, cwd, diffMode, ignoreWhitespace, serverId, workspaceId],
|
|
);
|
|
const reviewActions = useInlineReviewController({ reviewDraftKey, presentation });
|
|
const reviewAttachment = useReviewAttachmentSnapshot({
|
|
key: reviewDraftKey,
|
|
diffFiles: files,
|
|
cwd,
|
|
mode: diffMode,
|
|
baseRef,
|
|
});
|
|
|
|
const reviewFeedback = useReviewFeedback({
|
|
serverId,
|
|
workspaceId,
|
|
reviewDraftKey,
|
|
attachment: reviewAttachment,
|
|
});
|
|
|
|
return {
|
|
status,
|
|
isStatusLoading,
|
|
isGit,
|
|
notGit,
|
|
statusErrorMessage,
|
|
baseRef,
|
|
currentBranchName,
|
|
diffMode,
|
|
selectUncommitted,
|
|
selectBase,
|
|
selectAll,
|
|
files,
|
|
diffPayloadError,
|
|
diffTooLarge,
|
|
isDiffLoading,
|
|
reviewActions,
|
|
reviewAttachment,
|
|
reviewFeedback,
|
|
};
|
|
}
|
|
|
|
export function usePublishWorkingDiffAttachment({
|
|
serverId,
|
|
workspaceId,
|
|
cwd,
|
|
attachment,
|
|
enabled,
|
|
}: {
|
|
serverId: string;
|
|
workspaceId?: string;
|
|
cwd: string;
|
|
attachment: ReturnType<typeof useWorkingDiff>["reviewAttachment"];
|
|
enabled: boolean;
|
|
}) {
|
|
const scopeKey = useMemo(
|
|
() => buildWorkspaceAttachmentScopeKey({ serverId, workspaceId, cwd }),
|
|
[cwd, serverId, workspaceId],
|
|
);
|
|
const setWorkspaceAttachments = useWorkspaceAttachmentsStore(
|
|
(state) => state.setWorkspaceAttachments,
|
|
);
|
|
const clearWorkspaceAttachments = useWorkspaceAttachmentsStore(
|
|
(state) => state.clearWorkspaceAttachments,
|
|
);
|
|
|
|
useEffect(() => {
|
|
if (!enabled) {
|
|
return;
|
|
}
|
|
const attachments = attachment ? [attachment] : [];
|
|
setWorkspaceAttachments({ scopeKey, attachments });
|
|
return () => {
|
|
const current = useWorkspaceAttachmentsStore.getState().attachmentsByScope[scopeKey];
|
|
if (current === attachments) {
|
|
clearWorkspaceAttachments({ scopeKey });
|
|
}
|
|
};
|
|
}, [attachment, clearWorkspaceAttachments, enabled, scopeKey, setWorkspaceAttachments]);
|
|
}
|