Skip to content
Merged
Show file tree
Hide file tree
Changes from 7 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
1 change: 1 addition & 0 deletions apps/desktop/src/renderer/components/app/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -589,6 +589,7 @@ function ProjectTabHost() {
onboardingEnabled: s.onboardingEnabled,
didYouKnowEnabled: s.didYouKnowEnabled,
launchPromptClipboardEnabled: s.launchPromptClipboardEnabled,
launchPromptClipboardNoticeEnabled: s.launchPromptClipboardNoticeEnabled,
})));
const storesRef = React.useRef(new Map<string, AppStoreApi>());
const lruRef = React.useRef<string[]>([]);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@ const appStoreState = vi.hoisted(() => ({
project: { rootPath: "/fake/project" },
projectTransition: null as { kind: "opening" | "switching" | "closing"; rootPath: string | null; startedAtMs: number } | null,
theme: "dark",
launchPromptClipboardEnabled: true,
launchPromptClipboardNoticeEnabled: true,
openProjectTabRoots: [] as string[],
projectInfoByRoot: {} as Record<string, { rootPath: string; displayName?: string }>,
}));
Expand Down Expand Up @@ -186,6 +188,8 @@ describe("App Work route keep-alive", () => {
appStoreState.project = { rootPath: "/fake/project" };
appStoreState.projectTransition = null;
appStoreState.theme = "dark";
appStoreState.launchPromptClipboardEnabled = true;
appStoreState.launchPromptClipboardNoticeEnabled = true;
appStoreState.openProjectTabRoots = [];
appStoreState.projectInfoByRoot = {};
window.localStorage.clear();
Expand Down Expand Up @@ -228,6 +232,25 @@ describe("App Work route keep-alive", () => {
expect(workLifecycle.unmounts).toBe(0);
});

it("hydrates project stores with launch clipboard reminder preferences", async () => {
appStoreState.launchPromptClipboardNoticeEnabled = false;
const { hydrateProjectAppStore } = await import("../../state/appStore");
const { App } = await import("./App");

render(<App />);

await screen.findByTestId("work-page");
await waitFor(() => {
expect(hydrateProjectAppStore).toHaveBeenCalledWith(
expect.anything(),
expect.objectContaining({
launchPromptClipboardEnabled: true,
launchPromptClipboardNoticeEnabled: false,
}),
);
});
});

it("does not mount the Work page when hydration has not found a project yet", async () => {
appStoreState.projectHydrated = false;
appStoreState.project = { rootPath: "" };
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1423,6 +1423,20 @@ describe("AgentChatComposer", () => {
expect(screen.queryByText("After submission your prompt will auto copy to clipboard.")).toBeNull();
});

it("hides the launch clipboard helper when the reminder setting is disabled", () => {
renderComposer({
draft: "Copy silently",
turnActive: false,
launchPromptClipboardEnabled: true,
launchPromptClipboardNoticeEnabled: false,
});

fireEvent.focus(screen.getByRole("textbox"));

expect(screen.queryByText(/Prompt will be copied to clipboard after Send\./)).toBeNull();
expect(screen.queryByText("After submission your prompt will auto copy to clipboard.")).toBeNull();
});

it("focuses the grid composer when the tile becomes active", () => {
const props = buildComposerProps({
layoutVariant: "grid-tile",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -814,6 +814,7 @@ export function AgentChatComposer({
onOpenAiSettings,
onOpenLinearSettings,
launchPromptClipboardEnabled = false,
launchPromptClipboardNoticeEnabled = true,
onOpenLaunchPromptClipboardSettings,
onStartOrchestratorChat,
onStopOrchestratorChat,
Expand Down Expand Up @@ -965,6 +966,7 @@ export function AgentChatComposer({
onOpenAiSettings?: () => void;
onOpenLinearSettings?: () => void;
launchPromptClipboardEnabled?: boolean;
launchPromptClipboardNoticeEnabled?: boolean;
onOpenLaunchPromptClipboardSettings?: () => void;
/**
* Open the "New orchestrator chat" flow from the visible composer mode
Expand Down Expand Up @@ -1097,11 +1099,12 @@ export function AgentChatComposer({
const canAttachIssueContext = !composerInputLocked && typeof onAddContextAttachment === "function";
const showOrchestratorModeButton = Boolean(onStartOrchestratorChat && !sessionId && !parallelChatMode);
const orchestratorModeButtonDisabled = composerInputLocked || busy || turnActive;
const showLaunchClipboardHelper =
const showLaunchClipboardNotice =
launchPromptClipboardEnabled
&& composerFocused
&& launchPromptClipboardNoticeEnabled
&& !composerInputLocked
&& draft.trim().length > 0;
const showLaunchClipboardHelper = showLaunchClipboardNotice && composerFocused;

const resizeTextarea = useCallback(() => {
if (useRichComposer) return;
Expand Down Expand Up @@ -3358,7 +3361,7 @@ export function AgentChatComposer({
}
footer={
<div className="ade-chat-composer-footer flex flex-col gap-2 px-2 py-1 sm:px-2.5">
{launchPromptClipboardEnabled && draft.trim().length > 0 && !composerInputLocked ? (
{showLaunchClipboardNotice ? (
<div className="px-1 font-sans text-[length:calc(var(--chat-font-size)*10.5/14)] text-muted-fg/45">
After submission your prompt will auto copy to clipboard.
</div>
Expand Down
Loading