diff --git a/packages/app/e2e/browser/composer-diff-stat.spec.ts b/packages/app/e2e/browser/composer-diff-stat.spec.ts
index 00705faccd..b3d1b56c12 100644
--- a/packages/app/e2e/browser/composer-diff-stat.spec.ts
+++ b/packages/app/e2e/browser/composer-diff-stat.spec.ts
@@ -310,7 +310,7 @@ async function sendFeedback(page: Page, count: number) {
}
async function expectFeedbackSent(page: Page, recipient: string) {
- await expect(page.getByText(`Feedback sent to ${recipient}`, { exact: true })).toBeVisible();
+ await expect(page.getByTestId("app-toast")).toHaveText(`Feedback sent to ${recipient}`);
await expect(page.getByTestId("working-diff-panel")).toBeVisible();
}
@@ -340,6 +340,9 @@ test.describe("send review feedback", () => {
await expectFeedbackSent(page, "Composer diff stat");
await expectReviewAbsent(page, "Please simplify this.");
await captureFeedback(page, "single");
+ await expect(
+ page.getByText("Feedback sent to Composer diff stat", { exact: true }),
+ ).toHaveCount(0);
});
await test.step("Return to the untouched composer draft", async () => {
await showWideLayout(page);
@@ -375,11 +378,7 @@ test.describe("send review feedback", () => {
).toBeDisabled();
expect(gate.requestCount()).toBe(1);
gate.accept();
- await expect(
- compactReviewSurface(page).getByText("Feedback sent to Composer diff stat", {
- exact: true,
- }),
- ).toBeVisible();
+ await expectFeedbackSent(page, "Composer diff stat");
});
} finally {
await workspace.cleanup();
diff --git a/packages/app/src/review/feedback/index.test.ts b/packages/app/src/review/feedback/index.test.ts
index b423855b75..6ef6d74287 100644
--- a/packages/app/src/review/feedback/index.test.ts
+++ b/packages/app/src/review/feedback/index.test.ts
@@ -172,8 +172,7 @@ describe("review feedback", () => {
makeComment("added"),
]);
expect(feedback.model.getState().phase).toEqual({
- kind: "sent",
- recipient: makeRecipient("one"),
+ kind: "idle",
});
});
it("clears unchanged sent comments while preserving additions", async () => {
diff --git a/packages/app/src/review/feedback/index.ts b/packages/app/src/review/feedback/index.ts
index 69e0592fe8..3aaba5c97d 100644
--- a/packages/app/src/review/feedback/index.ts
+++ b/packages/app/src/review/feedback/index.ts
@@ -23,8 +23,7 @@ export type FeedbackPhase =
| { kind: "idle" }
| { kind: "choosing" }
| { kind: "sending"; recipient: FeedbackRecipient; commentCount: number }
- | { kind: "failed"; message: string }
- | { kind: "sent"; recipient: FeedbackRecipient };
+ | { kind: "failed"; message: string };
export interface ReviewFeedbackState {
phase: FeedbackPhase;
commentCount: number;
@@ -115,7 +114,7 @@ function createFeedbackView(
try {
await ports.send(recipient, attachment);
ports.clearSent(sentComments);
- workflow.changePhase({ kind: "sent", recipient });
+ workflow.changePhase({ kind: "idle" });
} catch (error) {
workflow.changePhase({
kind: "failed",
diff --git a/packages/app/src/review/feedback/surface.tsx b/packages/app/src/review/feedback/surface.tsx
index 7f87f46d88..fac499152e 100644
--- a/packages/app/src/review/feedback/surface.tsx
+++ b/packages/app/src/review/feedback/surface.tsx
@@ -80,17 +80,6 @@ function OpenReviewFeedbackAction({
let notice: ReactNode = unavailableNotice;
if (state.phase.kind === "failed")
notice = {state.phase.message};
- else if (state.phase.kind === "sent")
- notice = (
- <>
-
- {unavailableNotice}
- >
- );
return (
<>
{state.commentCount > 0 ? (
@@ -229,7 +218,7 @@ function RecipientRow({
);
}
-function SentNotice({
+export function FeedbackSentMessage({
recipient,
serverId,
workspaceId,
@@ -241,7 +230,7 @@ function SentNotice({
const { t } = useTranslation();
const render = useCallback(
(presentation: WorkspaceTabPresentation) => (
-
+
{t("review.feedback.sent", { recipient: presentation.label })}
),
@@ -267,6 +256,10 @@ const styles = StyleSheet.create((theme) => ({
left: theme.spacing[4],
alignItems: "flex-end",
},
+ sentMessage: {
+ color: theme.colors.foreground,
+ fontSize: theme.fontSize.sm,
+ },
text: {
color: theme.colors.foreground,
fontSize: theme.fontSize.sm,
diff --git a/packages/app/src/review/feedback/use-feedback.ts b/packages/app/src/review/feedback/use-feedback.ts
index e2b151953e..0596f3c55f 100644
--- a/packages/app/src/review/feedback/use-feedback.ts
+++ b/packages/app/src/review/feedback/use-feedback.ts
@@ -1,4 +1,4 @@
-import { useEffect, useMemo, useRef, useSyncExternalStore } from "react";
+import { createElement, useEffect, useMemo, useRef, useSyncExternalStore } from "react";
import {
useReviewDraftComments,
getReviewDraftComments,
@@ -22,6 +22,8 @@ import {
type FeedbackAttachment,
type FeedbackRecipient,
} from "./index";
+import { useToast } from "@/contexts/toast-context";
+import { FeedbackSentMessage } from "./surface";
const feedbackScope = createReviewFeedbackScope();
@@ -32,6 +34,7 @@ export function useReviewFeedback(input: {
attachment: FeedbackAttachment | null;
}) {
const { serverId, reviewDraftKey, workspaceId } = input;
+ const toast = useToast();
const isCompact = useIsCompactFormFactor();
const workspaceKey = workspaceId
? buildWorkspaceTabPersistenceKey({ serverId, workspaceId })
@@ -49,12 +52,14 @@ export function useReviewFeedback(input: {
connected,
attachment: input.attachment,
sendBehavior: settings.sendBehavior,
+ toast,
});
live.current = {
client,
connected,
attachment: input.attachment,
sendBehavior: settings.sendBehavior,
+ toast,
};
const model = useMemo(
() =>
@@ -85,12 +90,20 @@ export function useReviewFeedback(input: {
).turnId ?? undefined)
: undefined,
});
+ live.current.toast.show(
+ createElement(FeedbackSentMessage, {
+ recipient,
+ serverId,
+ workspaceId: workspaceId ?? "",
+ }),
+ { variant: "success" },
+ );
},
clearSent: (sentComments) =>
clearSentReviewDraftComments({ key: reviewDraftKey, comments: sentComments }),
failedMessage: () => i18n.t("review.feedback.failed"),
}),
- [reviewDraftKey, serverId, workspaceKey],
+ [reviewDraftKey, serverId, workspaceKey, workspaceId],
);
useEffect(() => {
model.refresh();