@agent-native/toolkit 0.209.1 → 0.209.2-nightly-20261016005836
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/agent-native.eject.json +3 -0
- package/dist/app/chat/AgentPanel.d.ts.map +1 -1
- package/dist/app/chat/AgentPanel.js +8 -3
- package/dist/app/chat/AgentPanel.js.map +1 -1
- package/dist/app/chat/AgentSidebar.d.ts.map +1 -1
- package/dist/app/chat/AgentSidebar.js +2 -0
- package/dist/app/chat/AgentSidebar.js.map +1 -1
- package/dist/app/chat/FileStorageSetupPopover.d.ts.map +1 -1
- package/dist/app/chat/FileStorageSetupPopover.js +11 -2
- package/dist/app/chat/FileStorageSetupPopover.js.map +1 -1
- package/dist/app/chat/agent-chat-presence.d.ts +3 -0
- package/dist/app/chat/agent-chat-presence.d.ts.map +1 -0
- package/dist/app/chat/agent-chat-presence.js +24 -0
- package/dist/app/chat/agent-chat-presence.js.map +1 -0
- package/dist/app/chat/chat/run-recovery.d.ts.map +1 -1
- package/dist/app/chat/chat/run-recovery.js +15 -3
- package/dist/app/chat/chat/run-recovery.js.map +1 -1
- package/dist/app/feedback/ReportProblemButton.d.ts +6 -0
- package/dist/app/feedback/ReportProblemButton.d.ts.map +1 -0
- package/dist/app/feedback/ReportProblemButton.js +17 -0
- package/dist/app/feedback/ReportProblemButton.js.map +1 -0
- package/dist/app/feedback/ReportProblemDialog.d.ts +6 -0
- package/dist/app/feedback/ReportProblemDialog.d.ts.map +1 -0
- package/dist/app/feedback/ReportProblemDialog.js +90 -0
- package/dist/app/feedback/ReportProblemDialog.js.map +1 -0
- package/dist/app/feedback/index.d.ts +1 -0
- package/dist/app/feedback/index.d.ts.map +1 -1
- package/dist/app/feedback/index.js +1 -0
- package/dist/app/feedback/index.js.map +1 -1
- package/dist/app/i18n/catalogs/ar-SA.d.ts.map +1 -1
- package/dist/app/i18n/catalogs/ar-SA.js +13 -0
- package/dist/app/i18n/catalogs/ar-SA.js.map +1 -1
- package/dist/app/i18n/catalogs/de-DE.d.ts.map +1 -1
- package/dist/app/i18n/catalogs/de-DE.js +9 -0
- package/dist/app/i18n/catalogs/de-DE.js.map +1 -1
- package/dist/app/i18n/catalogs/en-US.d.ts +9 -0
- package/dist/app/i18n/catalogs/en-US.d.ts.map +1 -1
- package/dist/app/i18n/catalogs/en-US.js +9 -0
- package/dist/app/i18n/catalogs/en-US.js.map +1 -1
- package/dist/app/i18n/catalogs/es-ES.d.ts.map +1 -1
- package/dist/app/i18n/catalogs/es-ES.js +10 -0
- package/dist/app/i18n/catalogs/es-ES.js.map +1 -1
- package/dist/app/i18n/catalogs/fr-FR.d.ts.map +1 -1
- package/dist/app/i18n/catalogs/fr-FR.js +10 -0
- package/dist/app/i18n/catalogs/fr-FR.js.map +1 -1
- package/dist/app/i18n/catalogs/hi-IN.d.ts.map +1 -1
- package/dist/app/i18n/catalogs/hi-IN.js +9 -0
- package/dist/app/i18n/catalogs/hi-IN.js.map +1 -1
- package/dist/app/i18n/catalogs/ja-JP.d.ts.map +1 -1
- package/dist/app/i18n/catalogs/ja-JP.js +8 -0
- package/dist/app/i18n/catalogs/ja-JP.js.map +1 -1
- package/dist/app/i18n/catalogs/ko-KR.d.ts.map +1 -1
- package/dist/app/i18n/catalogs/ko-KR.js +8 -0
- package/dist/app/i18n/catalogs/ko-KR.js.map +1 -1
- package/dist/app/i18n/catalogs/pt-BR.d.ts.map +1 -1
- package/dist/app/i18n/catalogs/pt-BR.js +10 -0
- package/dist/app/i18n/catalogs/pt-BR.js.map +1 -1
- package/dist/app/i18n/catalogs/zh-CN.d.ts.map +1 -1
- package/dist/app/i18n/catalogs/zh-CN.js +8 -0
- package/dist/app/i18n/catalogs/zh-CN.js.map +1 -1
- package/dist/app/i18n/catalogs/zh-TW.d.ts.map +1 -1
- package/dist/app/i18n/catalogs/zh-TW.js +8 -0
- package/dist/app/i18n/catalogs/zh-TW.js.map +1 -1
- package/dist/app/settings/BuilderConnectPopover.d.ts.map +1 -1
- package/dist/app/settings/BuilderConnectPopover.js +13 -7
- package/dist/app/settings/BuilderConnectPopover.js.map +1 -1
- package/dist/app/shared/AppSidebar.d.ts.map +1 -1
- package/dist/app/shared/AppSidebar.js +11 -3
- package/dist/app/shared/AppSidebar.js.map +1 -1
- package/dist/app/shared/CommandMenu.d.ts.map +1 -1
- package/dist/app/shared/CommandMenu.js +21 -4
- package/dist/app/shared/CommandMenu.js.map +1 -1
- package/dist/design-tweaks/scrub-input.d.ts +6 -0
- package/dist/design-tweaks/scrub-input.d.ts.map +1 -1
- package/dist/design-tweaks/scrub-input.js +12 -0
- package/dist/design-tweaks/scrub-input.js.map +1 -1
- package/dist/design-tweaks/visual-style-controls.d.ts +1 -1
- package/dist/design-tweaks/visual-style-controls.d.ts.map +1 -1
- package/dist/design-tweaks/visual-style-controls.js +1 -1
- package/dist/design-tweaks/visual-style-controls.js.map +1 -1
- package/package.json +4 -4
- package/src/app/chat/AgentPanel.header.spec.ts +1 -1
- package/src/app/chat/AgentPanel.tsx +23 -0
- package/src/app/chat/AgentSidebar.tsx +2 -0
- package/src/app/chat/FileStorageSetupPopover.spec.tsx +66 -5
- package/src/app/chat/FileStorageSetupPopover.tsx +15 -6
- package/src/app/chat/agent-chat-presence.ts +30 -0
- package/src/app/chat/chat/run-recovery.spec.tsx +60 -0
- package/src/app/chat/chat/run-recovery.tsx +28 -2
- package/src/app/feedback/ReportProblemButton.tsx +59 -0
- package/src/app/feedback/ReportProblemDialog.spec.tsx +190 -0
- package/src/app/feedback/ReportProblemDialog.tsx +212 -0
- package/src/app/feedback/index.ts +4 -0
- package/src/app/i18n/catalogs/ar-SA.ts +20 -0
- package/src/app/i18n/catalogs/de-DE.ts +12 -0
- package/src/app/i18n/catalogs/en-US.ts +12 -0
- package/src/app/i18n/catalogs/es-ES.ts +14 -0
- package/src/app/i18n/catalogs/fr-FR.ts +14 -0
- package/src/app/i18n/catalogs/hi-IN.ts +12 -0
- package/src/app/i18n/catalogs/ja-JP.ts +10 -0
- package/src/app/i18n/catalogs/ko-KR.ts +10 -0
- package/src/app/i18n/catalogs/pt-BR.ts +14 -0
- package/src/app/i18n/catalogs/zh-CN.ts +9 -0
- package/src/app/i18n/catalogs/zh-TW.ts +10 -0
- package/src/app/settings/BuilderConnectPopover.spec.tsx +19 -14
- package/src/app/settings/BuilderConnectPopover.tsx +80 -64
- package/src/app/shared/AppSidebar.spec.tsx +22 -1
- package/src/app/shared/AppSidebar.tsx +24 -3
- package/src/app/shared/CommandMenu.tsx +41 -1
- package/src/design-tweaks/scrub-input.tsx +19 -0
- package/src/design-tweaks/visual-style-controls.spec.tsx +31 -0
- package/src/design-tweaks/visual-style-controls.tsx +2 -0
|
@@ -92,45 +92,51 @@ export function BuilderConnectChoicePanel({
|
|
|
92
92
|
defaultValue: "Activate free credits",
|
|
93
93
|
})}
|
|
94
94
|
</h2>
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
"Creating your Builder.io account and activating free credits.",
|
|
105
|
-
})
|
|
106
|
-
: canProvisionAccount
|
|
107
|
-
? t("agentChat.onboarding.builderActivationDescription", {
|
|
95
|
+
{!flow.accountExists ? (
|
|
96
|
+
<p
|
|
97
|
+
id="builder-connect-popover-description"
|
|
98
|
+
className="text-xs leading-5 text-muted-foreground"
|
|
99
|
+
role={flow.connecting ? "status" : undefined}
|
|
100
|
+
aria-live={flow.connecting ? "polite" : undefined}
|
|
101
|
+
>
|
|
102
|
+
{flow.connecting
|
|
103
|
+
? t("agentChat.onboarding.builderProvisioningDescription", {
|
|
108
104
|
defaultValue:
|
|
109
|
-
"
|
|
105
|
+
"Creating your Builder.io account and activating free credits.",
|
|
110
106
|
})
|
|
111
|
-
:
|
|
112
|
-
? t("agentChat.onboarding.
|
|
107
|
+
: canProvisionAccount
|
|
108
|
+
? t("agentChat.onboarding.builderActivationDescription", {
|
|
113
109
|
defaultValue:
|
|
114
|
-
"
|
|
110
|
+
"Create a new account to activate free credits, or continue with an existing account.",
|
|
115
111
|
})
|
|
116
|
-
:
|
|
117
|
-
? t("agentChat.onboarding.
|
|
112
|
+
: statusReadFailed
|
|
113
|
+
? t("agentChat.onboarding.builderActivationCheckFailed", {
|
|
118
114
|
defaultValue:
|
|
119
|
-
"
|
|
115
|
+
"Couldn't check whether this app can create new accounts.",
|
|
120
116
|
})
|
|
121
|
-
: flow.
|
|
122
|
-
? t(
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
117
|
+
: flow.statusCheckEnabled === false
|
|
118
|
+
? t(
|
|
119
|
+
"agentChat.onboarding.builderActivationUnavailableInMode",
|
|
120
|
+
{
|
|
121
|
+
defaultValue:
|
|
122
|
+
"Create a Builder.io account or sign in to connect.",
|
|
123
|
+
},
|
|
124
|
+
)
|
|
125
|
+
: flow.statusResolved === false
|
|
126
|
+
? t("agentChat.onboarding.builderActivationChecking", {
|
|
127
|
+
defaultValue:
|
|
128
|
+
"Checking whether new account activation is available.",
|
|
129
|
+
})
|
|
130
|
+
: t("agentChat.onboarding.builderActivationUnavailable", {
|
|
131
|
+
defaultValue:
|
|
132
|
+
"Create a Builder.io account or sign in to connect.",
|
|
133
|
+
})}
|
|
134
|
+
</p>
|
|
135
|
+
) : null}
|
|
131
136
|
{flow.accountExists ? (
|
|
132
137
|
<div
|
|
133
138
|
role="alert"
|
|
139
|
+
id="builder-connect-popover-account-exists"
|
|
134
140
|
className="rounded-md bg-muted px-3 py-2 text-xs leading-5"
|
|
135
141
|
>
|
|
136
142
|
<p className="font-medium text-foreground">
|
|
@@ -177,7 +183,7 @@ export function BuilderConnectChoicePanel({
|
|
|
177
183
|
</div>
|
|
178
184
|
) : null}
|
|
179
185
|
<BuilderConnectIncludedServices appId={appId} />
|
|
180
|
-
{canProvisionAccount ? (
|
|
186
|
+
{canProvisionAccount && !flow.accountExists ? (
|
|
181
187
|
<div className="flex flex-col gap-2">
|
|
182
188
|
<Button
|
|
183
189
|
type="button"
|
|
@@ -214,45 +220,55 @@ export function BuilderConnectChoicePanel({
|
|
|
214
220
|
type="button"
|
|
215
221
|
data-testid={primaryTestId}
|
|
216
222
|
className="w-full"
|
|
217
|
-
aria-describedby=
|
|
223
|
+
aria-describedby={
|
|
224
|
+
flow.accountExists
|
|
225
|
+
? "builder-connect-popover-account-exists"
|
|
226
|
+
: "builder-connect-popover-description"
|
|
227
|
+
}
|
|
218
228
|
onClick={onExistingAccount}
|
|
219
229
|
disabled={flow.connecting}
|
|
220
230
|
>
|
|
221
231
|
{flow.connecting ? <Spinner aria-hidden /> : null}
|
|
222
|
-
{
|
|
223
|
-
|
|
224
|
-
|
|
232
|
+
{flow.accountExists
|
|
233
|
+
? t("agentChat.onboarding.builderExistingAccount", {
|
|
234
|
+
defaultValue: "I have a Builder.io account",
|
|
235
|
+
})
|
|
236
|
+
: t("agentChat.onboarding.builderConnect", {
|
|
237
|
+
defaultValue: "Connect Builder.io",
|
|
238
|
+
})}
|
|
225
239
|
</Button>
|
|
226
240
|
)}
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
241
|
+
{canProvisionAccount && !flow.accountExists ? (
|
|
242
|
+
<p className="text-[11px] leading-4 text-muted-foreground">
|
|
243
|
+
{t("agentChat.onboarding.builderConsentPrefix", {
|
|
244
|
+
defaultValue: "By creating a Builder.io account, you agree to our",
|
|
245
|
+
})}{" "}
|
|
246
|
+
<a
|
|
247
|
+
href="https://www.builder.io/legal/terms"
|
|
248
|
+
target="_blank"
|
|
249
|
+
rel="noreferrer"
|
|
250
|
+
className="underline underline-offset-2 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring"
|
|
251
|
+
>
|
|
252
|
+
{t("agentChat.onboarding.builderTerms", {
|
|
253
|
+
defaultValue: "Terms of Service",
|
|
254
|
+
})}
|
|
255
|
+
</a>{" "}
|
|
256
|
+
{t("agentChat.onboarding.builderConsentAnd", {
|
|
257
|
+
defaultValue: "and",
|
|
258
|
+
})}{" "}
|
|
259
|
+
<a
|
|
260
|
+
href="https://www.builder.io/legal/privacy"
|
|
261
|
+
target="_blank"
|
|
262
|
+
rel="noreferrer"
|
|
263
|
+
className="underline underline-offset-2 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring"
|
|
264
|
+
>
|
|
265
|
+
{t("agentChat.onboarding.builderPrivacy", {
|
|
266
|
+
defaultValue: "Privacy Policy",
|
|
267
|
+
})}
|
|
268
|
+
</a>
|
|
269
|
+
.
|
|
270
|
+
</p>
|
|
271
|
+
) : null}
|
|
256
272
|
</div>
|
|
257
273
|
);
|
|
258
274
|
}
|
|
@@ -6,7 +6,7 @@ import {
|
|
|
6
6
|
TooltipProvider,
|
|
7
7
|
TooltipTrigger,
|
|
8
8
|
} from "@agent-native/toolkit/ui/tooltip";
|
|
9
|
-
import { act } from "react";
|
|
9
|
+
import { act, type ReactNode } from "react";
|
|
10
10
|
import { createRoot, type Root } from "react-dom/client";
|
|
11
11
|
import { MemoryRouter, useLocation } from "react-router";
|
|
12
12
|
import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
|
|
@@ -61,6 +61,7 @@ describe("AppSidebar (router links)", () => {
|
|
|
61
61
|
"Slides",
|
|
62
62
|
"Decks",
|
|
63
63
|
"Settings",
|
|
64
|
+
"Report a problem",
|
|
64
65
|
"Expand sidebar",
|
|
65
66
|
]);
|
|
66
67
|
|
|
@@ -74,6 +75,26 @@ describe("AppSidebar (router links)", () => {
|
|
|
74
75
|
}
|
|
75
76
|
});
|
|
76
77
|
|
|
78
|
+
it("offers Report a problem beside the feedback row and hides it with feedback", () => {
|
|
79
|
+
const renderSidebar = (feedback: ReactNode) => (
|
|
80
|
+
<MemoryRouter>
|
|
81
|
+
<AppSidebar
|
|
82
|
+
showBadge={false}
|
|
83
|
+
brandName="Slides"
|
|
84
|
+
items={[{ label: "Decks", to: "/home" }]}
|
|
85
|
+
feedback={feedback}
|
|
86
|
+
/>
|
|
87
|
+
</MemoryRouter>
|
|
88
|
+
);
|
|
89
|
+
|
|
90
|
+
act(() => root.render(renderSidebar(<span>Send feedback</span>)));
|
|
91
|
+
expect(container.textContent).toContain("Send feedback");
|
|
92
|
+
expect(container.textContent).toContain("Report a problem");
|
|
93
|
+
|
|
94
|
+
act(() => root.render(renderSidebar(null)));
|
|
95
|
+
expect(container.textContent).not.toContain("Report a problem");
|
|
96
|
+
});
|
|
97
|
+
|
|
77
98
|
it("keeps rail and settings-gear tooltip links mounted across rerenders", () => {
|
|
78
99
|
const renderLinks = (revision: number) => (
|
|
79
100
|
<MemoryRouter>
|
|
@@ -9,10 +9,12 @@ import {
|
|
|
9
9
|
type AppSidebarHeaderProps as ToolkitAppSidebarHeaderProps,
|
|
10
10
|
type AppSidebarFooterProps as ToolkitAppSidebarFooterProps,
|
|
11
11
|
} from "@agent-native/toolkit/app-shell";
|
|
12
|
-
import {
|
|
12
|
+
import { cn } from "@agent-native/toolkit/utils";
|
|
13
|
+
import { forwardRef, type ReactNode } from "react";
|
|
13
14
|
import { useHref, useLinkClickHandler } from "react-router";
|
|
14
15
|
|
|
15
16
|
import { FeedbackButton } from "../feedback/FeedbackButton.js";
|
|
17
|
+
import { ReportProblemButton } from "../feedback/ReportProblemButton.js";
|
|
16
18
|
import { AgentNativeIcon } from "./AgentNativeIcon.js";
|
|
17
19
|
import { EnvironmentBadge } from "./EnvironmentBadge.js";
|
|
18
20
|
|
|
@@ -99,6 +101,25 @@ export const AppSidebarHeader = forwardRef<
|
|
|
99
101
|
);
|
|
100
102
|
AppSidebarHeader.displayName = "AppSidebarHeader";
|
|
101
103
|
|
|
104
|
+
// Every app's feedback row also offers Report a problem; an app that hides feedback hides both.
|
|
105
|
+
function withReportProblem(
|
|
106
|
+
feedback: ReactNode,
|
|
107
|
+
collapsed: boolean | undefined,
|
|
108
|
+
): ReactNode {
|
|
109
|
+
if (!feedback) return feedback;
|
|
110
|
+
return (
|
|
111
|
+
<div
|
|
112
|
+
className={cn(
|
|
113
|
+
"flex flex-col",
|
|
114
|
+
collapsed ? "items-center gap-1" : "gap-0.5",
|
|
115
|
+
)}
|
|
116
|
+
>
|
|
117
|
+
{feedback}
|
|
118
|
+
<ReportProblemButton variant={collapsed ? "icon" : "sidebar"} />
|
|
119
|
+
</div>
|
|
120
|
+
);
|
|
121
|
+
}
|
|
122
|
+
|
|
102
123
|
export interface AppSidebarFooterProps extends ToolkitAppSidebarFooterProps {}
|
|
103
124
|
|
|
104
125
|
export const AppSidebarFooter = forwardRef<
|
|
@@ -118,7 +139,7 @@ export const AppSidebarFooter = forwardRef<
|
|
|
118
139
|
<ToolkitAppSidebarFooter
|
|
119
140
|
ref={ref}
|
|
120
141
|
collapsed={collapsed}
|
|
121
|
-
feedback={resolvedFeedback}
|
|
142
|
+
feedback={withReportProblem(resolvedFeedback, collapsed)}
|
|
122
143
|
{...props}
|
|
123
144
|
/>
|
|
124
145
|
);
|
|
@@ -178,7 +199,7 @@ export const AppSidebar = forwardRef<HTMLElement, AppSidebarProps>(
|
|
|
178
199
|
badge={resolvedBadge}
|
|
179
200
|
linkComponent={resolvedLinkComponent}
|
|
180
201
|
{...props}
|
|
181
|
-
feedback={resolvedFeedback}
|
|
202
|
+
feedback={withReportProblem(resolvedFeedback, props.collapsed)}
|
|
182
203
|
/>
|
|
183
204
|
);
|
|
184
205
|
},
|
|
@@ -38,6 +38,7 @@ import {
|
|
|
38
38
|
IconExternalLink,
|
|
39
39
|
IconInfoCircle,
|
|
40
40
|
IconMessage,
|
|
41
|
+
IconMessageReport,
|
|
41
42
|
IconHistory,
|
|
42
43
|
IconLogout,
|
|
43
44
|
IconSettings,
|
|
@@ -54,6 +55,7 @@ import React, {
|
|
|
54
55
|
type ReactNode,
|
|
55
56
|
} from "react";
|
|
56
57
|
|
|
58
|
+
import { ReportProblemDialog } from "../feedback/ReportProblemDialog.js";
|
|
57
59
|
import { AboutAgentNativeDialog } from "./AboutAgentNativeDialog.js";
|
|
58
60
|
import { LazyChunkErrorBoundary } from "./LazyChunkErrorBoundary.js";
|
|
59
61
|
|
|
@@ -356,6 +358,7 @@ export function CommandMenu({
|
|
|
356
358
|
|
|
357
359
|
const [changelogOpen, setChangelogOpen] = useState(false);
|
|
358
360
|
const [aboutOpen, setAboutOpen] = useState(false);
|
|
361
|
+
const [reportProblemOpen, setReportProblemOpen] = useState(false);
|
|
359
362
|
const hasChangelog =
|
|
360
363
|
typeof changelog === "string" && changelog.trim().length > 0;
|
|
361
364
|
const showAbout = showAboutProp ?? hasChangelog;
|
|
@@ -374,6 +377,11 @@ export function CommandMenu({
|
|
|
374
377
|
setTimeout(() => setAboutOpen(true), 50);
|
|
375
378
|
}, [onOpenChange]);
|
|
376
379
|
|
|
380
|
+
const openReportProblem = useCallback(() => {
|
|
381
|
+
onOpenChange(false);
|
|
382
|
+
setTimeout(() => setReportProblemOpen(true), 50);
|
|
383
|
+
}, [onOpenChange]);
|
|
384
|
+
|
|
377
385
|
useEffect(() => {
|
|
378
386
|
if (!open) {
|
|
379
387
|
setSearch("");
|
|
@@ -451,6 +459,13 @@ export function CommandMenu({
|
|
|
451
459
|
.toLowerCase()
|
|
452
460
|
.includes(search.toLowerCase());
|
|
453
461
|
const showAboutRow = showAbout && aboutRowMatches;
|
|
462
|
+
const reportProblemLabel = t("agentChat.reportProblem.menuItem");
|
|
463
|
+
const showReportProblemRow =
|
|
464
|
+
!search ||
|
|
465
|
+
[reportProblemLabel, "bug", "issue", "problem", "report"]
|
|
466
|
+
.join(" ")
|
|
467
|
+
.toLowerCase()
|
|
468
|
+
.includes(search.toLowerCase());
|
|
454
469
|
const settingsLabel = t("settingsShortcut.command");
|
|
455
470
|
const showSettingsRow =
|
|
456
471
|
!search ||
|
|
@@ -600,12 +615,31 @@ export function CommandMenu({
|
|
|
600
615
|
</>
|
|
601
616
|
)}
|
|
602
617
|
|
|
603
|
-
{
|
|
618
|
+
{showReportProblemRow && (
|
|
604
619
|
<>
|
|
605
620
|
{(hasResults ||
|
|
606
621
|
showSettingsRow ||
|
|
607
622
|
showChangelogRow ||
|
|
608
623
|
showAboutRow) && <CommandSeparator />}
|
|
624
|
+
<div className="p-1">
|
|
625
|
+
<CommandItemPrimitive
|
|
626
|
+
className="cursor-pointer gap-2 py-2"
|
|
627
|
+
onSelect={openReportProblem}
|
|
628
|
+
>
|
|
629
|
+
<IconMessageReport className="h-4 w-4 text-muted-foreground" />
|
|
630
|
+
<span>{reportProblemLabel}</span>
|
|
631
|
+
</CommandItemPrimitive>
|
|
632
|
+
</div>
|
|
633
|
+
</>
|
|
634
|
+
)}
|
|
635
|
+
|
|
636
|
+
{showSignOutRow && (
|
|
637
|
+
<>
|
|
638
|
+
{(hasResults ||
|
|
639
|
+
showSettingsRow ||
|
|
640
|
+
showChangelogRow ||
|
|
641
|
+
showAboutRow ||
|
|
642
|
+
showReportProblemRow) && <CommandSeparator />}
|
|
609
643
|
<div className="p-1">
|
|
610
644
|
<CommandItemPrimitive
|
|
611
645
|
className="cursor-pointer gap-2 py-2"
|
|
@@ -624,6 +658,7 @@ export function CommandMenu({
|
|
|
624
658
|
showSettingsRow ||
|
|
625
659
|
showChangelogRow ||
|
|
626
660
|
showAboutRow ||
|
|
661
|
+
showReportProblemRow ||
|
|
627
662
|
showSignOutRow ||
|
|
628
663
|
Boolean(results)) && <CommandSeparator />}
|
|
629
664
|
<div className="p-1">
|
|
@@ -761,6 +796,11 @@ export function CommandMenu({
|
|
|
761
796
|
{showAbout && (
|
|
762
797
|
<AboutAgentNativeDialog open={aboutOpen} onOpenChange={setAboutOpen} />
|
|
763
798
|
)}
|
|
799
|
+
|
|
800
|
+
<ReportProblemDialog
|
|
801
|
+
open={reportProblemOpen}
|
|
802
|
+
onOpenChange={setReportProblemOpen}
|
|
803
|
+
/>
|
|
764
804
|
</>
|
|
765
805
|
);
|
|
766
806
|
}
|
|
@@ -91,6 +91,17 @@ interface PendingScrubTextCommit {
|
|
|
91
91
|
}
|
|
92
92
|
|
|
93
93
|
const activeScrubCancelCallbacks = new Set<() => void>();
|
|
94
|
+
const mountedScrubInputs = new Set<() => ScrubInputDisplay>();
|
|
95
|
+
|
|
96
|
+
export interface ScrubInputDisplay {
|
|
97
|
+
label: string;
|
|
98
|
+
shown: string;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
/** What each mounted scrub input is showing right now. */
|
|
102
|
+
export function readVisualScrubInputs(): ScrubInputDisplay[] {
|
|
103
|
+
return [...mountedScrubInputs].map((read) => read());
|
|
104
|
+
}
|
|
94
105
|
|
|
95
106
|
export function cancelActiveScrubInputs() {
|
|
96
107
|
for (const cancel of [...activeScrubCancelCallbacks]) cancel();
|
|
@@ -181,6 +192,14 @@ export function VisualScrubInput({
|
|
|
181
192
|
[],
|
|
182
193
|
);
|
|
183
194
|
|
|
195
|
+
useEffect(() => {
|
|
196
|
+
const read = () => ({ label: ariaLabel ?? label, shown: draftRef.current });
|
|
197
|
+
mountedScrubInputs.add(read);
|
|
198
|
+
return () => {
|
|
199
|
+
mountedScrubInputs.delete(read);
|
|
200
|
+
};
|
|
201
|
+
}, [ariaLabel, label]);
|
|
202
|
+
|
|
184
203
|
useEffect(() => {
|
|
185
204
|
if (mixed) {
|
|
186
205
|
pendingCommitRef.current = null;
|
|
@@ -11,6 +11,7 @@ import {
|
|
|
11
11
|
VisualSegmentedControl,
|
|
12
12
|
parseScrubExpression,
|
|
13
13
|
parseScrubRelativeExpression,
|
|
14
|
+
readVisualScrubInputs,
|
|
14
15
|
} from "./visual-style-controls.js";
|
|
15
16
|
|
|
16
17
|
describe("visual style controls", () => {
|
|
@@ -109,6 +110,36 @@ describe("visual style controls", () => {
|
|
|
109
110
|
},
|
|
110
111
|
);
|
|
111
112
|
|
|
113
|
+
it("reads what each mounted scrub input shows until it unmounts", () => {
|
|
114
|
+
act(() => {
|
|
115
|
+
root.render(
|
|
116
|
+
<>
|
|
117
|
+
<VisualScrubInput
|
|
118
|
+
label="Opacity"
|
|
119
|
+
value={91}
|
|
120
|
+
unit="%"
|
|
121
|
+
onChange={vi.fn()}
|
|
122
|
+
/>
|
|
123
|
+
<VisualScrubInput
|
|
124
|
+
label="Opacity"
|
|
125
|
+
value={40}
|
|
126
|
+
unit="%"
|
|
127
|
+
onChange={vi.fn()}
|
|
128
|
+
/>
|
|
129
|
+
</>,
|
|
130
|
+
);
|
|
131
|
+
});
|
|
132
|
+
|
|
133
|
+
expect(readVisualScrubInputs()).toEqual([
|
|
134
|
+
{ label: "Opacity", shown: "91%" },
|
|
135
|
+
{ label: "Opacity", shown: "40%" },
|
|
136
|
+
]);
|
|
137
|
+
|
|
138
|
+
act(() => root.render(<></>));
|
|
139
|
+
|
|
140
|
+
expect(readVisualScrubInputs()).toEqual([]);
|
|
141
|
+
});
|
|
142
|
+
|
|
112
143
|
it("starts a base-rate scrub when Option-drag begins on the numeric input", () => {
|
|
113
144
|
const onChange = vi.fn();
|
|
114
145
|
act(() => {
|
|
@@ -21,9 +21,11 @@ import { cn } from "../utils.js";
|
|
|
21
21
|
export {
|
|
22
22
|
cancelActiveScrubInputs,
|
|
23
23
|
VisualScrubInput,
|
|
24
|
+
readVisualScrubInputs,
|
|
24
25
|
resolvePendingScrubCommit,
|
|
25
26
|
type PendingScrubCommit,
|
|
26
27
|
type ScrubInputChangeMeta,
|
|
28
|
+
type ScrubInputDisplay,
|
|
27
29
|
type ScrubInputProps,
|
|
28
30
|
} from "./scrub-input.js";
|
|
29
31
|
export {
|