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
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
Loading