Skip to content
Open
Show file tree
Hide file tree
Changes from 1 commit
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
9 changes: 5 additions & 4 deletions packages/app/src/git/actions-split-button.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -182,10 +182,11 @@ export function GitActionsSplitButton({ gitActions, hideLabels }: GitActionsSpli
needsSeparator={action.startsGroup}
showSeparator={index > 0}
closeOnSelect={
action.status === "idle" &&
action.id === "pr" &&
action.label === action.pendingLabel &&
action.label === action.successLabel
action.id === "copy-pr-url" ||
(action.status === "idle" &&
action.id === "pr" &&
action.label === action.pendingLabel &&
action.label === action.successLabel)
}
/>
))}
Expand Down
3 changes: 3 additions & 0 deletions packages/app/src/git/diff-pane.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ import {
ArrowDownUp,
ChevronDown,
Columns2,
Copy,
Download,
GitCommitHorizontal,
GitMerge,
Expand Down Expand Up @@ -1111,6 +1112,7 @@ const ThemedGitHubIcon = withUnistyles(GitHubIcon);
const ThemedGitMerge = withUnistyles(GitMerge);
const ThemedRefreshCcw = withUnistyles(RefreshCcw);
const ThemedArchive = withUnistyles(Archive);
const ThemedCopy = withUnistyles(Copy);
const ThemedChevronDown = withUnistyles(ChevronDown);

interface DiffLayoutToggleGroupProps {
Expand Down Expand Up @@ -2100,6 +2102,7 @@ export function GitDiffPane({ serverId, workspaceId, cwd, enabled }: GitDiffPane
merge: <ThemedGitMerge size={16} uniProps={foregroundMutedIconColorMapping} />,
mergeFromBase: <ThemedRefreshCcw size={16} uniProps={foregroundMutedIconColorMapping} />,
archive: <ThemedArchive size={16} uniProps={foregroundMutedIconColorMapping} />,
copyPrUrl: <ThemedCopy size={16} uniProps={foregroundMutedIconColorMapping} />,
}),
[],
);
Expand Down
5 changes: 5 additions & 0 deletions packages/app/src/git/policy.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,11 @@ function createInput(overrides: Partial<BuildGitActionsInput> = {}): BuildGitAct
status: "idle",
handler: () => undefined,
},
"copy-pr-url": {
disabled: false,
status: "idle",
handler: () => undefined,
},
Comment on lines +130 to +134

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 No test assertions for the new action's ordering or visibility

The only change here is adding copy-pr-url to the fixture, which is required to keep existing tests compiling. There are no new test cases verifying that copy-pr-url appears immediately after pr in the secondary list, that it is absent when hasPullRequest is false, or that it is absent when pullRequestUrl is null. Given the injection logic lives in a for-loop inside buildGitActions, a policy test covering these three cases would be the natural place to pin the behavior.

Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!

},
...overrides,
};
Expand Down
24 changes: 22 additions & 2 deletions packages/app/src/git/policy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,8 @@ export type GitActionId =
| "disable-pr-auto-merge"
| "merge-branch"
| "merge-from-base"
| "archive-worktree";
| "archive-worktree"
| "copy-pr-url";

export interface GitAction {
id: GitActionId;
Expand Down Expand Up @@ -298,12 +299,31 @@ export function buildGitActions(input: BuildGitActionsInput): GitActions {
handler: input.runtime["archive-worktree"].handler,
});

if (input.hasPullRequest && input.pullRequestUrl) {
allActions.set("copy-pr-url", {
id: "copy-pr-url",
label: i18n.t("workspace.git.actions.copyPrUrl"),
pendingLabel: i18n.t("workspace.git.actions.copyPrUrl"),
successLabel: i18n.t("workspace.git.actions.copyPrUrl"),
disabled: input.runtime["copy-pr-url"].disabled,
status: input.runtime["copy-pr-url"].status,
icon: input.runtime["copy-pr-url"].icon,
startsGroup: false,
handler: input.runtime["copy-pr-url"].handler,
});
}

const primaryActionId = getPrimaryActionId(input);
const primary = primaryActionId ? (allActions.get(primaryActionId) ?? null) : null;

const secondaryIds = [...REMOTE_ACTION_IDS];
if (!input.isOnBaseBranch) {
secondaryIds.push(...getFeatureActionIds(input));
for (const id of getFeatureActionIds(input)) {
secondaryIds.push(id);
if (id === "pr" && input.hasPullRequest && input.pullRequestUrl) {
secondaryIds.push("copy-pr-url");
}
}
}
if (input.isPaseoOwnedWorktree) {
secondaryIds.push("archive-worktree");
Expand Down
22 changes: 22 additions & 0 deletions packages/app/src/git/use-actions.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import {
} from "@/git/policy";
import type { CheckoutPrMergeMethod } from "@getpaseo/protocol/messages";
import { openExternalUrl } from "@/utils/open-external-url";
import { copyToClipboard } from "@/utils/copy-to-clipboard";
import { useToast } from "@/contexts/toast-context";
import { useSessionStore } from "@/stores/session-store";
import {
Expand Down Expand Up @@ -154,6 +155,7 @@ interface UseGitActionsInput {
merge: ReactElement;
mergeFromBase: ReactElement;
archive: ReactElement;
copyPrUrl: ReactElement;
};
}

Expand Down Expand Up @@ -567,6 +569,13 @@ export function useGitActions({ serverId, cwd, icons }: UseGitActionsInput): Use
handleCreatePr();
}, [prStatus?.url, handleCreatePr]);

const handleCopyPrUrl = useCallback(() => {
if (prStatus?.url) {
void copyToClipboard(prStatus.url);
toast.show(t("workspace.git.actions.copyPrUrlSuccess"), { variant: "success" });
}
}, [prStatus?.url, toast, t]);
Comment thread
greptile-apps[bot] marked this conversation as resolved.
Outdated

// Build actions
const gitActions: GitActions = useMemo(() => {
const actions = buildGitActions({
Expand Down Expand Up @@ -683,6 +692,12 @@ export function useGitActions({ serverId, cwd, icons }: UseGitActionsInput): Use
icon: icons.archive,
handler: handleArchiveWorktree,
},
"copy-pr-url": {
disabled: false,
status: "idle",
icon: icons.copyPrUrl,
handler: handleCopyPrUrl,
},
},
});
return translateGitActions(actions, { baseRefLabel, hasPullRequest, t });
Expand Down Expand Up @@ -736,6 +751,7 @@ export function useGitActions({ serverId, cwd, icons }: UseGitActionsInput): Use
handleMergeBranch,
handleMergeFromBase,
handleArchiveWorktree,
handleCopyPrUrl,
icons,
baseRef,
]);
Expand Down Expand Up @@ -890,6 +906,12 @@ function getTranslatedGitActionLabels(
pendingLabel: t("workspace.git.actions.archive.pending"),
successLabel: t("workspace.git.actions.archive.success"),
};
case "copy-pr-url":
return {
label: t("workspace.git.actions.copyPrUrl"),
pendingLabel: t("workspace.git.actions.copyPrUrl"),
successLabel: t("workspace.git.actions.copyPrUrl"),
};
}
}

Expand Down
3 changes: 3 additions & 0 deletions packages/app/src/git/workspace-actions.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { withUnistyles } from "react-native-unistyles";
import {
Archive,
ArrowDownUp,
Copy,
Download,
GitCommitHorizontal,
GitMerge,
Expand All @@ -27,6 +28,7 @@ const ThemedGitHubIcon = withUnistyles(GitHubIcon);
const ThemedGitMerge = withUnistyles(GitMerge);
const ThemedRefreshCcw = withUnistyles(RefreshCcw);
const ThemedArchive = withUnistyles(Archive);
const ThemedCopy = withUnistyles(Copy);

const mutedColorMapping = (theme: Theme) => ({
color: theme.colors.foregroundMuted,
Expand All @@ -45,6 +47,7 @@ const ICONS = {
merge: <ThemedGitMerge size={16} uniProps={mutedColorMapping} />,
mergeFromBase: <ThemedRefreshCcw size={16} uniProps={mutedColorMapping} />,
archive: <ThemedArchive size={16} uniProps={mutedColorMapping} />,
copyPrUrl: <ThemedCopy size={16} uniProps={mutedColorMapping} />,
};

export function WorkspaceGitActions({ serverId, cwd, hideLabels }: WorkspaceGitActionsProps) {
Expand Down
2 changes: 2 additions & 0 deletions packages/app/src/i18n/resources/ar.ts
Original file line number Diff line number Diff line change
Expand Up @@ -583,6 +583,8 @@ export const ar: TranslationResources = {
success: "سحبت ودفعت",
},
viewPr: "عرض PR",
copyPrUrl: "نسخ رابط PR",
copyPrUrlSuccess: "تم نسخ الرابط",
createPr: {
label: "إنشاء PR",
pending: "إنشاء PR...",
Expand Down
2 changes: 2 additions & 0 deletions packages/app/src/i18n/resources/en.ts
Original file line number Diff line number Diff line change
Expand Up @@ -582,6 +582,8 @@ export const en = {
success: "Pulled and pushed",
},
viewPr: "View PR",
copyPrUrl: "Copy PR URL",
copyPrUrlSuccess: "URL copied",
createPr: {
label: "Create PR",
pending: "Creating PR...",
Expand Down
2 changes: 2 additions & 0 deletions packages/app/src/i18n/resources/es.ts
Original file line number Diff line number Diff line change
Expand Up @@ -589,6 +589,8 @@ export const es: TranslationResources = {
success: "Tirado y empujado",
},
viewPr: "VerPR",
copyPrUrl: "Copiar URL del PR",
copyPrUrlSuccess: "URL copiada",
createPr: {
label: "CrearPR",
pending: "CreandoPR...",
Expand Down
2 changes: 2 additions & 0 deletions packages/app/src/i18n/resources/fr.ts
Original file line number Diff line number Diff line change
Expand Up @@ -589,6 +589,8 @@ export const fr: TranslationResources = {
success: "Tiré et poussé",
},
viewPr: "VoirPR",
copyPrUrl: "Copier l'URL du PR",
copyPrUrlSuccess: "URL copiée",
createPr: {
label: "CréerPR",
pending: "Création dePR...",
Expand Down
2 changes: 2 additions & 0 deletions packages/app/src/i18n/resources/ru.ts
Original file line number Diff line number Diff line change
Expand Up @@ -588,6 +588,8 @@ export const ru: TranslationResources = {
success: "Вытащил и толкнул",
},
viewPr: "Посмотреть PR",
copyPrUrl: "Скопировать URL PR",
copyPrUrlSuccess: "URL скопирован",
createPr: {
label: "Создать PR",
pending: "Создание PR...",
Expand Down
2 changes: 2 additions & 0 deletions packages/app/src/i18n/resources/zh-CN.ts
Original file line number Diff line number Diff line change
Expand Up @@ -581,6 +581,8 @@ export const zhCN: TranslationResources = {
success: "已 pull 并 push",
},
viewPr: "查看 PR",
copyPrUrl: "复制 PR 链接",
copyPrUrlSuccess: "链接已复制",
createPr: {
label: "创建 PR",
pending: "正在创建 PR...",
Expand Down