Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 12 additions & 6 deletions apps/dashboard/src/components/compare/compare-diff-view.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -37,11 +37,13 @@ const noopEdit = (_a: PendingComment, _b: string) => {};
export function CompareDiffView({
commits,
files,
filesTruncated = false,
owner,
repo,
}: {
commits: PullCommit[];
files: PullFile[];
filesTruncated?: boolean;
owner: string;
repo: string;
}) {
Expand All @@ -52,13 +54,10 @@ export function CompareDiffView({
const loadMoreRef = useRef<HTMLDivElement>(null);

useEffect(() => {
setVisibleCount((prev) =>
Math.min(
files.length,
Math.max(files.length === 0 ? 0 : INITIAL_VISIBLE_COUNT, prev),
),
setVisibleCount(
Math.min(files.length, files.length === 0 ? 0 : INITIAL_VISIBLE_COUNT),
);
}, [files.length]);
}, [files]);

useEffect(() => {
if (visibleCount >= files.length) return;
Expand Down Expand Up @@ -202,6 +201,13 @@ export function CompareDiffView({
</div>
) : null}
</div>
{filesTruncated ? (
<p className="rounded-lg border border-yellow-500/40 bg-yellow-500/10 px-4 py-2.5 text-xs text-yellow-700 dark:text-yellow-400">
This comparison includes more than {files.length} files; GitHub only
returns the first {files.length}. Push fewer changes or open the PR
to view the full set.
</p>
) : null}
{files.length === 0 ? (
<p className="rounded-lg border bg-surface-0 px-4 py-3 text-sm text-muted-foreground">
No files changed.
Expand Down
16 changes: 8 additions & 8 deletions apps/dashboard/src/components/compare/compare-header.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -65,16 +65,16 @@ export function CompareHeader({
{aheadBy === 1 ? "commit" : "commits"} ahead
</span>
) : null}
{aheadBy > 0 && behindBy > 0 ? (
<span className="text-muted-foreground/50">·</span>
) : null}
{behindBy > 0 ? (
<>
<span className="text-muted-foreground/50">·</span>
<span className="flex items-center gap-1">
<span className="tabular-nums font-medium text-foreground">
{behindBy}
</span>
{behindBy === 1 ? "commit" : "commits"} behind
<span className="flex items-center gap-1">
<span className="tabular-nums font-medium text-foreground">
{behindBy}
</span>
</>
{behindBy === 1 ? "commit" : "commits"} behind
</span>
) : null}
{status === "identical" ? <span>Branches are identical</span> : null}
</span>
Expand Down
46 changes: 38 additions & 8 deletions apps/dashboard/src/components/compare/compare-page.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import type { MentionCandidate } from "@diffkit/ui/components/markdown-editor";
import { toast } from "@diffkit/ui/components/sonner";
import { useQuery, useQueryClient } from "@tanstack/react-query";
import { useRouter } from "@tanstack/react-router";
import { useCallback, useEffect, useMemo, useRef, useState } from "react";
Expand Down Expand Up @@ -179,19 +180,27 @@ export function ComparePage({
});

if (result.ok) {
const INVALIDATE_SEGMENTS = new Set([
"pulls",
"overview",
"recentPushableBranch",
"branchComparison",
"compareDetail",
]);
await queryClient.invalidateQueries({
predicate: (query) => {
const key = query.queryKey;
return (
Array.isArray(key) &&
key.some(
(k) =>
typeof k === "string" &&
(k.includes("pulls") || k.includes("repoMeta")),
)
if (!Array.isArray(key)) return false;
return key.some(
(k) => typeof k === "string" && INVALIDATE_SEGMENTS.has(k),
);
},
});
if (result.warnings && result.warnings.length > 0) {
toast.warning("Pull request created with some issues", {
description: result.warnings.join("\n"),
});
}
router.navigate({
to: "/$owner/$repo/pull/$pullId",
params: { owner, repo, pullId: String(result.pullNumber) },
Expand Down Expand Up @@ -223,7 +232,27 @@ export function ComparePage({

if (overviewQuery.error) throw overviewQuery.error;
if (compareQuery.error) throw compareQuery.error;
if (!repoData || !compare) return <ComparePageSkeleton />;
if (overviewQuery.isPending || compareQuery.isPending) {
return <ComparePageSkeleton />;
}
if (!repoData) return <ComparePageSkeleton />;
if (!compare) {
return (
<div className="mx-auto flex max-w-2xl flex-col items-center gap-3 px-6 py-20 text-center">
<h1 className="text-lg font-semibold">Nothing to compare</h1>
<p className="text-sm text-muted-foreground">
<code className="rounded bg-surface-2 px-1.5 py-0.5 font-mono text-xs">
{base}
</code>{" "}
and{" "}
<code className="rounded bg-surface-2 px-1.5 py-0.5 font-mono text-xs">
{head}
</code>{" "}
are identical, or one of them doesn't exist.
</p>
</div>
);
}

return (
<div className="h-full overflow-auto">
Expand Down Expand Up @@ -280,6 +309,7 @@ export function ComparePage({
<CompareDiffView
commits={compare.commits}
files={compare.files}
filesTruncated={compare.filesTruncated}
owner={owner}
repo={repo}
/>
Expand Down
45 changes: 30 additions & 15 deletions apps/dashboard/src/components/compare/compare-sidebar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import {
} from "@diffkit/ui/components/popover";
import { cn } from "@diffkit/ui/lib/utils";
import { useQuery, useQueryClient } from "@tanstack/react-query";
import { useCallback, useMemo, useRef, useState } from "react";
import { forwardRef, useCallback, useMemo, useRef, useState } from "react";
import { DetailSidebar } from "#/components/details/detail-sidebar";
import {
type GitHubQueryScope,
Expand Down Expand Up @@ -94,18 +94,39 @@ function SidebarSectionHeader({
);
}

function PickerTrigger({ onPrefetch }: { onPrefetch?: () => void }) {
const PickerTrigger = forwardRef<
HTMLButtonElement,
React.ButtonHTMLAttributes<HTMLButtonElement> & {
label: string;
onPrefetch?: () => void;
}
>(function PickerTrigger(
{ label, onPrefetch, onMouseEnter, onFocus, className, ...props },
ref,
) {
return (
<button
ref={ref}
type="button"
onMouseEnter={onPrefetch}
onFocus={onPrefetch}
className="flex size-5 items-center justify-center rounded text-muted-foreground transition-colors hover:bg-surface-2 hover:text-foreground"
aria-label={label}
onMouseEnter={(e) => {
onPrefetch?.();
onMouseEnter?.(e);
}}
onFocus={(e) => {
onPrefetch?.();
onFocus?.(e);
}}
className={cn(
"flex size-5 items-center justify-center rounded text-muted-foreground transition-colors hover:bg-surface-2 hover:text-foreground",
className,
)}
{...props}
>
<PlusSignIcon size={14} strokeWidth={2} />
</button>
);
}
});

function PickerSearchInput({
value,
Expand Down Expand Up @@ -222,9 +243,7 @@ function LabelsPicker({
}}
>
<PopoverTrigger asChild>
<span>
<PickerTrigger />
</span>
<PickerTrigger label="Add labels" />
</PopoverTrigger>
<PopoverContent align="end" className="w-64 p-0">
<PickerSearchInput
Expand Down Expand Up @@ -394,9 +413,7 @@ function AssigneesPicker({
}}
>
<PopoverTrigger asChild>
<span>
<PickerTrigger onPrefetch={prefetch} />
</span>
<PickerTrigger label="Add assignees" onPrefetch={prefetch} />
</PopoverTrigger>
<PopoverContent align="end" className="w-64 p-0">
<PickerSearchInput
Expand Down Expand Up @@ -612,9 +629,7 @@ function ReviewersPicker({
}}
>
<PopoverTrigger asChild>
<span>
<PickerTrigger onPrefetch={prefetch} />
</span>
<PickerTrigger label="Add reviewers" onPrefetch={prefetch} />
</PopoverTrigger>
<PopoverContent align="end" className="w-64 p-0">
<PickerSearchInput
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,16 +24,19 @@ export function BranchComparisonBanner({
currentBranch: string;
defaultBranch: string;
}) {
const isSameBranch = currentBranch === defaultBranch;
const comparisonQuery = useQuery({
...githubBranchComparisonQueryOptions(scope, {
owner,
repo,
base: defaultBranch,
head: currentBranch,
}),
enabled: currentBranch !== defaultBranch,
enabled: !isSameBranch,
});

if (isSameBranch) return null;

if (comparisonQuery.isPending) {
return (
<Callout variant="default">
Expand Down
Loading
Loading