@agent-native/core 0.178.0 → 0.178.1-nightly-20260909221943
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/corpus/README.md +1 -1
- package/corpus/templates/clips/.agents/skills/dictate/SKILL.md +1 -0
- package/corpus/templates/clips/DESIGN.md +10 -7
- package/corpus/templates/clips/actions/list-organization-state.ts +56 -3
- package/corpus/templates/clips/actions/list-recordings.ts +2 -0
- package/corpus/templates/clips/actions/search-dictations.ts +81 -0
- package/corpus/templates/clips/app/components/agent-destination-logos.tsx +50 -0
- package/corpus/templates/clips/app/components/bug-report/bug-report-dialog.tsx +60 -0
- package/corpus/templates/clips/app/components/bug-report/bug-report-form.tsx +206 -0
- package/corpus/templates/clips/app/components/clips-command-menu.tsx +653 -0
- package/corpus/templates/clips/app/components/library/empty-state.tsx +52 -17
- package/corpus/templates/clips/app/components/library/folder-card.tsx +34 -0
- package/corpus/templates/clips/app/components/library/folder-tree.tsx +109 -64
- package/corpus/templates/clips/app/components/library/library-action-hrefs.ts +27 -0
- package/corpus/templates/clips/app/components/library/library-grid.tsx +295 -103
- package/corpus/templates/clips/app/components/library/library-layout.tsx +381 -203
- package/corpus/templates/clips/app/components/library/library-primary-actions.tsx +48 -0
- package/corpus/templates/clips/app/components/library/page-header.tsx +48 -8
- package/corpus/templates/clips/app/components/library/recording-card.tsx +58 -55
- package/corpus/templates/clips/app/components/library/search-bar.tsx +5 -19
- package/corpus/templates/clips/app/components/library/sidebar-feedback-button.tsx +48 -0
- package/corpus/templates/clips/app/components/player/comments-panel.tsx +2 -2
- package/corpus/templates/clips/app/components/player/share-dialog.tsx +344 -260
- package/corpus/templates/clips/app/components/player/viewer-controls.tsx +2 -2
- package/corpus/templates/clips/app/components/recorder/camera-visualizer.tsx +0 -33
- package/corpus/templates/clips/app/components/sharing/share-ui.tsx +5 -1
- package/corpus/templates/clips/app/components/ui/tabs.tsx +1 -1
- package/corpus/templates/clips/app/hooks/use-command-search.ts +53 -0
- package/corpus/templates/clips/app/hooks/use-navigation-state.ts +32 -13
- package/corpus/templates/clips/app/hooks/use-upload-video-picker.tsx +1 -0
- package/corpus/templates/clips/app/i18n/en-US.ts +7 -0
- package/corpus/templates/clips/app/lib/agent-share.ts +16 -0
- package/corpus/templates/clips/app/lib/command-events.ts +7 -0
- package/corpus/templates/clips/app/root.tsx +6 -82
- package/corpus/templates/clips/app/routes/_app.dictate.tsx +25 -5
- package/corpus/templates/clips/app/routes/_app.library._index.tsx +2 -30
- package/corpus/templates/clips/app/routes/_app.library.folder.$folderId.tsx +13 -2
- package/corpus/templates/clips/app/routes/_app.meetings._index.tsx +4 -17
- package/corpus/templates/clips/app/routes/_app.r.$recordingId.tsx +111 -114
- package/corpus/templates/clips/app/routes/_app.spaces.$spaceId.folder.$folderId.tsx +25 -2
- package/corpus/templates/clips/app/routes/_app.spaces.$spaceId.tsx +14 -61
- package/corpus/templates/clips/app/routes/_app.spaces._index.tsx +34 -24
- package/corpus/templates/clips/app/routes/_app.trash.tsx +1 -1
- package/corpus/templates/clips/app/routes/_app.tsx +2 -4
- package/corpus/templates/clips/app/routes/bug-report.tsx +11 -189
- package/corpus/templates/clips/app/routes/share.$shareId.tsx +148 -123
- package/corpus/templates/clips/changelog/2026-09-08-comments-and-desktop-window-controls.md +6 -0
- package/corpus/templates/clips/changelog/2026-09-08-global-command-search.md +6 -0
- package/corpus/templates/clips/changelog/2026-09-09-agent-sidebar-fits-below-toolbar.md +6 -0
- package/corpus/templates/clips/changelog/2026-09-09-desktop-switches-stay-clear-in-dark-mode.md +6 -0
- package/corpus/templates/clips/changelog/2026-09-09-recording-agent-uses-global-panel.md +6 -0
- package/corpus/templates/clips/desktop/src/app.tsx +2 -2
- package/corpus/templates/clips/desktop/src/components/MediaDeviceRow.tsx +5 -3
- package/corpus/templates/clips/desktop/src/components/SourceRow.tsx +1 -0
- package/corpus/templates/clips/desktop/src/components/Switch.tsx +2 -5
- package/corpus/templates/clips/desktop/src/components/ui/switch.tsx +21 -3
- package/corpus/templates/clips/desktop/src/hooks/useMediaDevices.ts +72 -52
- package/corpus/templates/clips/desktop/src/styles.css +18 -19
- package/corpus/templates/clips/desktop/src/tailwind.css +3 -0
- package/corpus/templates/clips/desktop/src-tauri/src/lib.rs +18 -10
- package/corpus/templates/clips/desktop/src-tauri/src/util.rs +3 -5
- package/corpus/templates/design/.agents/skills/export-handoff/SKILL.md +14 -3
- package/corpus/templates/design/AGENTS.md +2 -1
- package/corpus/templates/design/actions/export-png.ts +119 -0
- package/corpus/templates/design/actions/take-design-screenshot.ts +47 -13
- package/corpus/templates/design/server/plugins/agent-chat.ts +3 -1
- package/corpus/templates/factory/actions/dispatch-factory-item.ts +51 -22
- package/corpus/templates/factory/actions/list-triage-items.ts +21 -11
- package/corpus/templates/factory/actions/poll-slack-channel.ts +7 -2
- package/corpus/templates/factory/changelog/2026-09-09-slack-feedback-keeps-claimed-markers-after-poll.md +6 -0
- package/corpus/templates/factory/changelog/2026-09-09-slack-feedback-preserves-started-claimed-threads.md +6 -0
- package/corpus/templates/factory/changelog/2026-09-09-slack-feedback-skips-claimed-parents.md +6 -0
- package/corpus/templates/factory/server/lib/factory-automation-config.ts +1 -1
- package/corpus/templates/factory/server/lib/slack-feedback-prompt.ts +47 -0
- package/corpus/templates/factory/server/plugins/agent-chat.ts +5 -2
- package/corpus/templates/factory/server/plugins/factory-scheduler-job.ts +5 -4
- package/corpus/templates/factory/server/triage/review-skill-alignment.ts +12 -7
- package/corpus/templates/factory/server/triage/slack-review-window.ts +39 -0
- package/dist/client/CommandMenu.js +13 -1
- package/dist/client/analytics.js +10 -0
- package/dist/collab/routes.d.ts +1 -1
- package/dist/file-upload/actions/upload-image.d.ts +1 -1
- package/dist/notifications/routes.d.ts +2 -2
- package/dist/observability/routes.d.ts +5 -5
- package/dist/vite/client.js +25 -7
- package/dist/vite/sentry-source-maps.d.ts +12 -0
- package/dist/vite/sentry-source-maps.js +105 -0
- package/package.json +2 -1
|
@@ -1,30 +1,13 @@
|
|
|
1
|
-
import { appBasePath } from "@agent-native/core/client/api-path";
|
|
2
|
-
import { useT } from "@agent-native/core/client/i18n";
|
|
3
1
|
import {
|
|
4
2
|
BUG_REPORT_POPUP_RESPONSE_HEADERS,
|
|
5
|
-
bugReportContextToSearchParams,
|
|
6
3
|
isBugReportSubmissionMessage,
|
|
7
4
|
parseBugReportContext,
|
|
8
|
-
type BugReportContext,
|
|
9
|
-
type BugReportSeverity,
|
|
10
5
|
} from "@shared/bug-report";
|
|
11
|
-
import {
|
|
12
|
-
import { useEffect, useMemo, useRef, useState } from "react";
|
|
6
|
+
import { useEffect, useMemo, useRef } from "react";
|
|
13
7
|
import { useLocation, useOutlet } from "react-router";
|
|
14
8
|
|
|
15
|
-
import {
|
|
16
|
-
import { Input } from "@/components/ui/input";
|
|
17
|
-
import { Label } from "@/components/ui/label";
|
|
18
|
-
import {
|
|
19
|
-
Select,
|
|
20
|
-
SelectContent,
|
|
21
|
-
SelectItem,
|
|
22
|
-
SelectTrigger,
|
|
23
|
-
SelectValue,
|
|
24
|
-
} from "@/components/ui/select";
|
|
25
|
-
import { Textarea } from "@/components/ui/textarea";
|
|
9
|
+
import { BugReportForm } from "@/components/bug-report/bug-report-form";
|
|
26
10
|
import enMessages from "@/i18n/en-US";
|
|
27
|
-
import { cn } from "@/lib/utils";
|
|
28
11
|
|
|
29
12
|
export function meta() {
|
|
30
13
|
return [{ title: enMessages.bugReportRoute.pageTitle }];
|
|
@@ -34,20 +17,6 @@ export function headers() {
|
|
|
34
17
|
return BUG_REPORT_POPUP_RESPONSE_HEADERS;
|
|
35
18
|
}
|
|
36
19
|
|
|
37
|
-
function openRecorder(url: string): Window | null {
|
|
38
|
-
const opened = window.open(
|
|
39
|
-
url,
|
|
40
|
-
"agent-native-clips-bug-report",
|
|
41
|
-
"popup,width=1120,height=820",
|
|
42
|
-
);
|
|
43
|
-
if (!opened) {
|
|
44
|
-
window.location.href = url;
|
|
45
|
-
return null;
|
|
46
|
-
}
|
|
47
|
-
opened.focus();
|
|
48
|
-
return opened;
|
|
49
|
-
}
|
|
50
|
-
|
|
51
20
|
function originFor(value: string | null): string | null {
|
|
52
21
|
if (!value) return null;
|
|
53
22
|
try {
|
|
@@ -58,7 +27,6 @@ function originFor(value: string | null): string | null {
|
|
|
58
27
|
}
|
|
59
28
|
|
|
60
29
|
export default function BugReportRoute() {
|
|
61
|
-
const t = useT();
|
|
62
30
|
const location = useLocation();
|
|
63
31
|
const outlet = useOutlet();
|
|
64
32
|
const initialContext = useMemo(() => {
|
|
@@ -66,28 +34,10 @@ export default function BugReportRoute() {
|
|
|
66
34
|
return parseBugReportContext(params, { allowLoose: true });
|
|
67
35
|
}, [location.search]);
|
|
68
36
|
|
|
69
|
-
const [title, setTitle] = useState(initialContext?.title ?? "");
|
|
70
|
-
const [description, setDescription] = useState(
|
|
71
|
-
initialContext?.description ?? "",
|
|
72
|
-
);
|
|
73
|
-
const [reporterEmail, setReporterEmail] = useState(
|
|
74
|
-
initialContext?.reporterEmail ?? "",
|
|
75
|
-
);
|
|
76
|
-
const [severity, setSeverity] = useState<BugReportSeverity>(
|
|
77
|
-
initialContext?.severity ?? "normal",
|
|
78
|
-
);
|
|
79
|
-
const [referrer, setReferrer] = useState<string | null>(null);
|
|
80
37
|
const recorderWindowRef = useRef<Window | null>(null);
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
}, []);
|
|
85
|
-
|
|
86
|
-
const sourceUrl = initialContext?.sourceUrl ?? referrer;
|
|
87
|
-
const pageTitle = initialContext?.pageTitle ?? null;
|
|
88
|
-
const sourceLabel =
|
|
89
|
-
pageTitle || sourceUrl || t("bugReportRoute.sourceUnknown");
|
|
90
|
-
const hostOrigin = originFor(initialContext?.returnUrl ?? sourceUrl);
|
|
38
|
+
const hostOrigin = originFor(
|
|
39
|
+
initialContext?.returnUrl ?? initialContext?.sourceUrl ?? null,
|
|
40
|
+
);
|
|
91
41
|
|
|
92
42
|
useEffect(() => {
|
|
93
43
|
if (!hostOrigin) return;
|
|
@@ -110,144 +60,16 @@ export default function BugReportRoute() {
|
|
|
110
60
|
|
|
111
61
|
if (outlet) return outlet;
|
|
112
62
|
|
|
113
|
-
const startRecording = () => {
|
|
114
|
-
const context: BugReportContext = {
|
|
115
|
-
projectId: initialContext?.projectId ?? null,
|
|
116
|
-
title: title.trim() || initialContext?.title || null,
|
|
117
|
-
description: description.trim() || initialContext?.description || null,
|
|
118
|
-
severity,
|
|
119
|
-
sourceUrl,
|
|
120
|
-
pageTitle,
|
|
121
|
-
appVersion: initialContext?.appVersion ?? null,
|
|
122
|
-
environment: initialContext?.environment ?? null,
|
|
123
|
-
reporterEmail:
|
|
124
|
-
reporterEmail.trim() || initialContext?.reporterEmail || null,
|
|
125
|
-
reporterName: initialContext?.reporterName ?? null,
|
|
126
|
-
reporterId: initialContext?.reporterId ?? null,
|
|
127
|
-
metadata: initialContext?.metadata ?? null,
|
|
128
|
-
returnUrl: initialContext?.returnUrl ?? sourceUrl,
|
|
129
|
-
};
|
|
130
|
-
const params = bugReportContextToSearchParams(context);
|
|
131
|
-
params.set("intent", "bug-report");
|
|
132
|
-
params.set("mode", "screen");
|
|
133
|
-
params.set("surface", "browser");
|
|
134
|
-
recorderWindowRef.current = openRecorder(
|
|
135
|
-
`${appBasePath()}/record?${params.toString()}`,
|
|
136
|
-
);
|
|
137
|
-
};
|
|
138
|
-
|
|
139
63
|
return (
|
|
140
64
|
<main className="min-h-screen bg-background text-foreground">
|
|
141
65
|
<div className="mx-auto flex min-h-screen w-full max-w-xl flex-col justify-center px-4 py-5 sm:px-6">
|
|
142
66
|
<section className="rounded-lg border bg-card p-4 shadow-sm sm:p-5">
|
|
143
|
-
<
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
{t("bugReportRoute.eyebrow")}
|
|
150
|
-
</p>
|
|
151
|
-
<h1 className="mt-1 text-xl font-semibold leading-tight">
|
|
152
|
-
{t("bugReportRoute.title")}
|
|
153
|
-
</h1>
|
|
154
|
-
<p className="mt-2 text-sm leading-6 text-muted-foreground">
|
|
155
|
-
{t("bugReportRoute.description")}
|
|
156
|
-
</p>
|
|
157
|
-
</div>
|
|
158
|
-
</div>
|
|
159
|
-
|
|
160
|
-
<div className="space-y-4">
|
|
161
|
-
<div className="space-y-2">
|
|
162
|
-
<Label htmlFor="bug-title">
|
|
163
|
-
{t("bugReportRoute.issueTitleLabel")}
|
|
164
|
-
</Label>
|
|
165
|
-
<Input
|
|
166
|
-
id="bug-title"
|
|
167
|
-
value={title}
|
|
168
|
-
onChange={(event) => setTitle(event.target.value)}
|
|
169
|
-
placeholder={t("bugReportRoute.issueTitlePlaceholder")}
|
|
170
|
-
/>
|
|
171
|
-
</div>
|
|
172
|
-
|
|
173
|
-
<div className="space-y-2">
|
|
174
|
-
<Label htmlFor="bug-details">
|
|
175
|
-
{t("bugReportRoute.detailsLabel")}
|
|
176
|
-
</Label>
|
|
177
|
-
<Textarea
|
|
178
|
-
id="bug-details"
|
|
179
|
-
value={description}
|
|
180
|
-
onChange={(event) => setDescription(event.target.value)}
|
|
181
|
-
placeholder={t("bugReportRoute.detailsPlaceholder")}
|
|
182
|
-
className="min-h-24 resize-none"
|
|
183
|
-
/>
|
|
184
|
-
</div>
|
|
185
|
-
|
|
186
|
-
<div className="grid gap-4 sm:grid-cols-[1fr_180px]">
|
|
187
|
-
<div className="space-y-2">
|
|
188
|
-
<Label htmlFor="bug-email">
|
|
189
|
-
{t("bugReportRoute.emailLabel")}
|
|
190
|
-
</Label>
|
|
191
|
-
<Input
|
|
192
|
-
id="bug-email"
|
|
193
|
-
type="email"
|
|
194
|
-
value={reporterEmail}
|
|
195
|
-
onChange={(event) => setReporterEmail(event.target.value)}
|
|
196
|
-
placeholder={t("bugReportRoute.emailPlaceholder")}
|
|
197
|
-
/>
|
|
198
|
-
</div>
|
|
199
|
-
<div className="space-y-2">
|
|
200
|
-
<Label>{t("bugReportRoute.severityLabel")}</Label>
|
|
201
|
-
<Select
|
|
202
|
-
value={severity}
|
|
203
|
-
onValueChange={(value) =>
|
|
204
|
-
setSeverity(value as BugReportSeverity)
|
|
205
|
-
}
|
|
206
|
-
>
|
|
207
|
-
<SelectTrigger>
|
|
208
|
-
<SelectValue />
|
|
209
|
-
</SelectTrigger>
|
|
210
|
-
<SelectContent>
|
|
211
|
-
<SelectItem value="low">
|
|
212
|
-
{t("bugReportRoute.severityLow")}
|
|
213
|
-
</SelectItem>
|
|
214
|
-
<SelectItem value="normal">
|
|
215
|
-
{t("bugReportRoute.severityNormal")}
|
|
216
|
-
</SelectItem>
|
|
217
|
-
<SelectItem value="high">
|
|
218
|
-
{t("bugReportRoute.severityHigh")}
|
|
219
|
-
</SelectItem>
|
|
220
|
-
<SelectItem value="urgent">
|
|
221
|
-
{t("bugReportRoute.severityUrgent")}
|
|
222
|
-
</SelectItem>
|
|
223
|
-
</SelectContent>
|
|
224
|
-
</Select>
|
|
225
|
-
</div>
|
|
226
|
-
</div>
|
|
227
|
-
|
|
228
|
-
<div className="rounded-md border bg-muted/40 px-3 py-2">
|
|
229
|
-
<p className="text-xs font-medium text-muted-foreground">
|
|
230
|
-
{t("bugReportRoute.sourceLabel")}
|
|
231
|
-
</p>
|
|
232
|
-
<p
|
|
233
|
-
className={cn(
|
|
234
|
-
"mt-1 truncate text-sm",
|
|
235
|
-
!sourceUrl && "text-muted-foreground",
|
|
236
|
-
)}
|
|
237
|
-
>
|
|
238
|
-
{sourceLabel}
|
|
239
|
-
</p>
|
|
240
|
-
</div>
|
|
241
|
-
|
|
242
|
-
<Button className="h-11 w-full" onClick={startRecording}>
|
|
243
|
-
{t("bugReportRoute.startRecording")}
|
|
244
|
-
</Button>
|
|
245
|
-
</div>
|
|
246
|
-
|
|
247
|
-
<div className="mt-5 flex items-start gap-2 rounded-md bg-muted/50 p-3 text-xs leading-5 text-muted-foreground">
|
|
248
|
-
<IconShieldCheck size={16} className="mt-0.5 shrink-0" />
|
|
249
|
-
<p>{t("bugReportRoute.privacyNote")}</p>
|
|
250
|
-
</div>
|
|
67
|
+
<BugReportForm
|
|
68
|
+
initialContext={initialContext}
|
|
69
|
+
onRecorderOpened={(recorderWindow) => {
|
|
70
|
+
recorderWindowRef.current = recorderWindow;
|
|
71
|
+
}}
|
|
72
|
+
/>
|
|
251
73
|
</section>
|
|
252
74
|
</div>
|
|
253
75
|
</main>
|
|
@@ -167,7 +167,7 @@ type SharePageLoaderData = {
|
|
|
167
167
|
accessRequestToken?: string;
|
|
168
168
|
};
|
|
169
169
|
|
|
170
|
-
type SharePanel = "transcript" | "agent";
|
|
170
|
+
type SharePanel = "comments" | "transcript" | "agent";
|
|
171
171
|
|
|
172
172
|
type PendingAccountAction =
|
|
173
173
|
| { intent: "comment"; atMs: number }
|
|
@@ -515,6 +515,15 @@ export default function ShareRoute() {
|
|
|
515
515
|
const [panel, setPanel] = useState<SharePanel>("transcript");
|
|
516
516
|
const [descriptionExpanded, setDescriptionExpanded] = useState(false);
|
|
517
517
|
const commentsSectionRef = useRef<HTMLElement | null>(null);
|
|
518
|
+
const selectCommentsPanel = useCallback(() => {
|
|
519
|
+
setPanel("comments");
|
|
520
|
+
requestAnimationFrame(() => {
|
|
521
|
+
commentsSectionRef.current?.scrollIntoView({
|
|
522
|
+
behavior: "smooth",
|
|
523
|
+
block: "start",
|
|
524
|
+
});
|
|
525
|
+
});
|
|
526
|
+
}, []);
|
|
518
527
|
const [downloading, setDownloading] = useState(false);
|
|
519
528
|
const [accessRequestSent, setAccessRequestSent] = useState(false);
|
|
520
529
|
const [accessRequestError, setAccessRequestError] = useState<string | null>(
|
|
@@ -1411,104 +1420,110 @@ export default function ShareRoute() {
|
|
|
1411
1420
|
</header>
|
|
1412
1421
|
|
|
1413
1422
|
<div className="flex w-full min-w-0 flex-none flex-col overflow-visible lg:col-start-1 lg:row-start-2 lg:min-h-0 lg:flex-1 lg:overflow-y-hidden">
|
|
1414
|
-
<main className="overflow-visible lg:min-h-0 lg:flex-1 lg:overflow-
|
|
1415
|
-
|
|
1416
|
-
|
|
1417
|
-
|
|
1418
|
-
|
|
1419
|
-
|
|
1420
|
-
|
|
1421
|
-
|
|
1422
|
-
|
|
1423
|
-
recording.
|
|
1424
|
-
|
|
1425
|
-
|
|
1426
|
-
|
|
1427
|
-
|
|
1428
|
-
|
|
1429
|
-
|
|
1430
|
-
|
|
1431
|
-
|
|
1432
|
-
|
|
1433
|
-
|
|
1434
|
-
|
|
1435
|
-
|
|
1436
|
-
|
|
1437
|
-
|
|
1438
|
-
|
|
1439
|
-
|
|
1440
|
-
|
|
1441
|
-
|
|
1442
|
-
|
|
1443
|
-
|
|
1444
|
-
|
|
1445
|
-
|
|
1446
|
-
|
|
1447
|
-
|
|
1448
|
-
|
|
1449
|
-
|
|
1450
|
-
|
|
1451
|
-
|
|
1452
|
-
|
|
1453
|
-
|
|
1454
|
-
|
|
1455
|
-
|
|
1456
|
-
|
|
1457
|
-
|
|
1458
|
-
|
|
1459
|
-
|
|
1460
|
-
|
|
1461
|
-
|
|
1462
|
-
return;
|
|
1463
|
-
}
|
|
1464
|
-
setCommentAtMs(resolvePlaybackMs());
|
|
1465
|
-
setCommentOpen(true);
|
|
1466
|
-
}
|
|
1467
|
-
: undefined
|
|
1468
|
-
}
|
|
1469
|
-
enableReactions={
|
|
1470
|
-
recording.enableReactions &&
|
|
1471
|
-
viewerCanUseFullscreenInteractions
|
|
1472
|
-
}
|
|
1473
|
-
onReact={
|
|
1474
|
-
viewerCanUseFullscreenInteractions
|
|
1475
|
-
? reactToRecording
|
|
1476
|
-
: undefined
|
|
1477
|
-
}
|
|
1478
|
-
className="h-full w-full rounded-none sm:rounded-xl"
|
|
1479
|
-
/>
|
|
1480
|
-
{commentOpen && viewerCanComment
|
|
1481
|
-
? (() => {
|
|
1482
|
-
const composer = (
|
|
1483
|
-
<TimestampedCommentBar
|
|
1484
|
-
recordingId={recording.id}
|
|
1485
|
-
atMs={commentAtMs}
|
|
1486
|
-
draft={commentDraft}
|
|
1487
|
-
onDraftChange={setCommentDraft}
|
|
1488
|
-
onClose={() => setCommentOpen(false)}
|
|
1489
|
-
onAdded={() => {
|
|
1490
|
-
void dataQ.refetch();
|
|
1491
|
-
if (resumedAccountActionRef.current === "comment") {
|
|
1492
|
-
resumedAccountActionRef.current = null;
|
|
1493
|
-
trackEvent("share_account_action_completed", {
|
|
1494
|
-
surface: "public_share",
|
|
1495
|
-
recording_id: recording.id,
|
|
1496
|
-
intent: "comment",
|
|
1497
|
-
});
|
|
1423
|
+
<main className="overflow-visible lg:min-h-0 lg:flex-1 lg:overflow-hidden">
|
|
1424
|
+
{/* Match the authenticated viewer's YouTube-like desktop measure so
|
|
1425
|
+
the discussion stays close to the video on wide displays. */}
|
|
1426
|
+
<div className="mx-auto flex w-full flex-col gap-5 pb-10 sm:px-4 lg:h-full lg:min-h-0 lg:max-w-[min(100%,1600px,calc(177.778dvh-35.556rem))] lg:pt-4">
|
|
1427
|
+
<div className="flex w-full shrink-0 justify-center">
|
|
1428
|
+
<div className="relative aspect-video w-full">
|
|
1429
|
+
<VideoPlayer
|
|
1430
|
+
ref={playerRef}
|
|
1431
|
+
onVideoElementChange={setTrackedVideoEl}
|
|
1432
|
+
recordingId={recording.id}
|
|
1433
|
+
videoUrl={recording.videoUrl}
|
|
1434
|
+
mediaVersion={
|
|
1435
|
+
recording.mediaUpdatedAt ?? recording.videoSizeBytes ?? null
|
|
1436
|
+
}
|
|
1437
|
+
videoFormat={recording.videoFormat}
|
|
1438
|
+
embedProvider={isLoomEmbedBacked ? "loom" : null}
|
|
1439
|
+
durationMs={recording.durationMs}
|
|
1440
|
+
startMs={resolveStartMs(startMs, recording.durationMs)}
|
|
1441
|
+
persistPlaybackPosition={Boolean(session)}
|
|
1442
|
+
editsJson={recording.editsJson}
|
|
1443
|
+
thumbnailUrl={recording.thumbnailUrl}
|
|
1444
|
+
role={viewerRole ?? (viewerCanEdit ? "owner" : "viewer")}
|
|
1445
|
+
defaultSpeed={
|
|
1446
|
+
parsePlaybackSpeed(recording.defaultSpeed) ?? 1.2
|
|
1447
|
+
}
|
|
1448
|
+
comments={comments}
|
|
1449
|
+
chapters={chapters}
|
|
1450
|
+
reactions={reactions}
|
|
1451
|
+
transcriptSegments={transcriptSegments}
|
|
1452
|
+
cta={firstCta}
|
|
1453
|
+
onCtaClick={() => tracking.reportCtaClick()}
|
|
1454
|
+
onTimeUpdate={(ms) => setCurrentMs(ms)}
|
|
1455
|
+
onCommentClick={
|
|
1456
|
+
viewerCanUseFullscreenInteractions
|
|
1457
|
+
? selectCommentsPanel
|
|
1458
|
+
: undefined
|
|
1459
|
+
}
|
|
1460
|
+
onFullscreenChange={setIsPlayerFullscreen}
|
|
1461
|
+
enableComments={
|
|
1462
|
+
recording.enableComments &&
|
|
1463
|
+
viewerCanUseFullscreenInteractions
|
|
1464
|
+
}
|
|
1465
|
+
onAddComment={
|
|
1466
|
+
viewerCanUseFullscreenInteractions
|
|
1467
|
+
? () => {
|
|
1468
|
+
if (!session) {
|
|
1469
|
+
requireSignIn("comment");
|
|
1470
|
+
return;
|
|
1498
1471
|
}
|
|
1499
|
-
|
|
1500
|
-
|
|
1501
|
-
|
|
1502
|
-
|
|
1503
|
-
|
|
1504
|
-
|
|
1505
|
-
|
|
1506
|
-
|
|
1507
|
-
|
|
1508
|
-
|
|
1509
|
-
|
|
1510
|
-
|
|
1511
|
-
|
|
1472
|
+
const liveMs = resolvePlaybackMs();
|
|
1473
|
+
setCurrentMs(liveMs);
|
|
1474
|
+
if (!isPlayerFullscreen) {
|
|
1475
|
+
selectCommentsPanel();
|
|
1476
|
+
return;
|
|
1477
|
+
}
|
|
1478
|
+
setCommentAtMs(liveMs);
|
|
1479
|
+
setCommentOpen(true);
|
|
1480
|
+
}
|
|
1481
|
+
: undefined
|
|
1482
|
+
}
|
|
1483
|
+
enableReactions={
|
|
1484
|
+
recording.enableReactions &&
|
|
1485
|
+
viewerCanUseFullscreenInteractions
|
|
1486
|
+
}
|
|
1487
|
+
onReact={
|
|
1488
|
+
viewerCanUseFullscreenInteractions
|
|
1489
|
+
? reactToRecording
|
|
1490
|
+
: undefined
|
|
1491
|
+
}
|
|
1492
|
+
className="h-full w-full rounded-none sm:rounded-xl"
|
|
1493
|
+
/>
|
|
1494
|
+
{commentOpen && viewerCanComment
|
|
1495
|
+
? (() => {
|
|
1496
|
+
const composer = (
|
|
1497
|
+
<TimestampedCommentBar
|
|
1498
|
+
recordingId={recording.id}
|
|
1499
|
+
atMs={commentAtMs}
|
|
1500
|
+
draft={commentDraft}
|
|
1501
|
+
onDraftChange={setCommentDraft}
|
|
1502
|
+
onClose={() => setCommentOpen(false)}
|
|
1503
|
+
onAdded={() => {
|
|
1504
|
+
void dataQ.refetch();
|
|
1505
|
+
if (resumedAccountActionRef.current === "comment") {
|
|
1506
|
+
resumedAccountActionRef.current = null;
|
|
1507
|
+
trackEvent("share_account_action_completed", {
|
|
1508
|
+
surface: "public_share",
|
|
1509
|
+
recording_id: recording.id,
|
|
1510
|
+
intent: "comment",
|
|
1511
|
+
});
|
|
1512
|
+
}
|
|
1513
|
+
}}
|
|
1514
|
+
/>
|
|
1515
|
+
);
|
|
1516
|
+
// The Fullscreen API only paints the player's own element,
|
|
1517
|
+
// so portal the composer there instead of exiting
|
|
1518
|
+
// fullscreen when it's open.
|
|
1519
|
+
const fullscreenContainer =
|
|
1520
|
+
isPlayerFullscreen && playerRef.current?.container;
|
|
1521
|
+
return fullscreenContainer
|
|
1522
|
+
? createPortal(composer, fullscreenContainer)
|
|
1523
|
+
: composer;
|
|
1524
|
+
})()
|
|
1525
|
+
: null}
|
|
1526
|
+
</div>
|
|
1512
1527
|
</div>
|
|
1513
1528
|
|
|
1514
1529
|
<section className="flex shrink-0 flex-col gap-3 px-4 pt-1 sm:px-0">
|
|
@@ -1619,11 +1634,42 @@ export default function ShareRoute() {
|
|
|
1619
1634
|
</div>
|
|
1620
1635
|
) : null}
|
|
1621
1636
|
</section>
|
|
1637
|
+
</div>
|
|
1638
|
+
</main>
|
|
1639
|
+
</div>
|
|
1622
1640
|
|
|
1623
|
-
|
|
1641
|
+
<Tabs
|
|
1642
|
+
value={panel}
|
|
1643
|
+
onValueChange={(value) => setPanel(value as SharePanel)}
|
|
1644
|
+
className="contents"
|
|
1645
|
+
>
|
|
1646
|
+
<RecordingSidePanel
|
|
1647
|
+
className="lg:col-start-2 lg:row-start-2"
|
|
1648
|
+
tabs={
|
|
1649
|
+
<ViewerTabsList>
|
|
1650
|
+
{recording.enableComments ? (
|
|
1651
|
+
<ViewerTabsTrigger value="comments">
|
|
1652
|
+
{t("sharePage.comments")}
|
|
1653
|
+
</ViewerTabsTrigger>
|
|
1654
|
+
) : null}
|
|
1655
|
+
<ViewerTabsTrigger value="transcript">
|
|
1656
|
+
{t("sharePage.transcript")}
|
|
1657
|
+
</ViewerTabsTrigger>
|
|
1658
|
+
<ViewerTabsTrigger value="agent">
|
|
1659
|
+
{t("sharePage.agent")}
|
|
1660
|
+
</ViewerTabsTrigger>
|
|
1661
|
+
</ViewerTabsList>
|
|
1662
|
+
}
|
|
1663
|
+
>
|
|
1664
|
+
{recording.enableComments ? (
|
|
1665
|
+
<TabsContent
|
|
1666
|
+
forceMount
|
|
1667
|
+
value="comments"
|
|
1668
|
+
className="mt-0 flex min-h-0 flex-1 flex-col overflow-hidden data-[state=inactive]:hidden"
|
|
1669
|
+
>
|
|
1624
1670
|
<section
|
|
1625
1671
|
ref={commentsSectionRef}
|
|
1626
|
-
className="
|
|
1672
|
+
className="flex min-h-0 flex-1 flex-col overflow-hidden px-3 pb-3 pt-3"
|
|
1627
1673
|
>
|
|
1628
1674
|
<h2 className="mb-3 shrink-0 text-sm font-semibold">
|
|
1629
1675
|
{t("sharePage.comments")}
|
|
@@ -1655,29 +1701,8 @@ export default function ShareRoute() {
|
|
|
1655
1701
|
presentation="inline"
|
|
1656
1702
|
/>
|
|
1657
1703
|
</section>
|
|
1658
|
-
|
|
1659
|
-
|
|
1660
|
-
</main>
|
|
1661
|
-
</div>
|
|
1662
|
-
|
|
1663
|
-
<Tabs
|
|
1664
|
-
value={panel}
|
|
1665
|
-
onValueChange={(value) => setPanel(value as SharePanel)}
|
|
1666
|
-
className="contents"
|
|
1667
|
-
>
|
|
1668
|
-
<RecordingSidePanel
|
|
1669
|
-
className="lg:col-start-2 lg:row-start-2"
|
|
1670
|
-
tabs={
|
|
1671
|
-
<ViewerTabsList>
|
|
1672
|
-
<ViewerTabsTrigger value="transcript">
|
|
1673
|
-
{t("sharePage.transcript")}
|
|
1674
|
-
</ViewerTabsTrigger>
|
|
1675
|
-
<ViewerTabsTrigger value="agent">
|
|
1676
|
-
{t("sharePage.agent")}
|
|
1677
|
-
</ViewerTabsTrigger>
|
|
1678
|
-
</ViewerTabsList>
|
|
1679
|
-
}
|
|
1680
|
-
>
|
|
1704
|
+
</TabsContent>
|
|
1705
|
+
) : null}
|
|
1681
1706
|
<TabsContent
|
|
1682
1707
|
value="agent"
|
|
1683
1708
|
className="mt-0 flex min-h-0 flex-1 flex-col overflow-y-auto"
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
---
|
|
2
|
+
type: fixed
|
|
3
|
+
date: 2026-09-08
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
Fixed desktop comment threads by keeping them in a full-height viewer tab, polished the side-panel tabs and spacing, added move, minimize, and close controls to desktop Clips windows, corrected the shared New recording action’s split-button corners, made library sub-item selection clear in the sidebar, and added visible folder tiles plus scoped recording actions to library and space views.
|
|
@@ -898,7 +898,7 @@ function SettingsSwitch({
|
|
|
898
898
|
onCheckedChange={onCheckedChange}
|
|
899
899
|
disabled={disabled}
|
|
900
900
|
aria-label={label}
|
|
901
|
-
|
|
901
|
+
tone="success"
|
|
902
902
|
/>
|
|
903
903
|
);
|
|
904
904
|
}
|
|
@@ -1351,7 +1351,7 @@ export function App({
|
|
|
1351
1351
|
loadDevices,
|
|
1352
1352
|
requestDeviceAccess,
|
|
1353
1353
|
} = useMediaDevices({
|
|
1354
|
-
|
|
1354
|
+
microphoneEnabled: micOn,
|
|
1355
1355
|
popoverVisible,
|
|
1356
1356
|
setCameraError,
|
|
1357
1357
|
setRecError,
|
|
@@ -131,7 +131,7 @@ export function MediaDeviceRow({
|
|
|
131
131
|
</DropdownMenuTrigger>
|
|
132
132
|
) : (
|
|
133
133
|
<span
|
|
134
|
-
className="row-button row-button-placeholder
|
|
134
|
+
className="row-button row-button-placeholder"
|
|
135
135
|
aria-disabled="true"
|
|
136
136
|
>
|
|
137
137
|
{label}
|
|
@@ -191,8 +191,10 @@ export function MediaDeviceRow({
|
|
|
191
191
|
</div>
|
|
192
192
|
</div>
|
|
193
193
|
{kind === "mic" && onSystemAudioToggle ? (
|
|
194
|
-
<div
|
|
195
|
-
|
|
194
|
+
<div
|
|
195
|
+
className={`row ${systemAudio ? "row-on" : "row-off"} system-audio-row`}
|
|
196
|
+
>
|
|
197
|
+
<span className="row-icon system-audio-icon" aria-hidden>
|
|
196
198
|
<IconVolume2 size={20} stroke={1.75} />
|
|
197
199
|
</span>
|
|
198
200
|
<span className="system-audio-label">Record system audio</span>
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import * as React from "react";
|
|
2
2
|
|
|
3
|
-
import { cn } from "../lib/utils";
|
|
4
3
|
import { Switch as UiSwitch } from "./ui/switch";
|
|
5
4
|
|
|
6
5
|
interface SwitchProps extends Omit<
|
|
@@ -31,10 +30,8 @@ export const Switch = React.forwardRef<
|
|
|
31
30
|
aria-label={label}
|
|
32
31
|
disabled={disabled}
|
|
33
32
|
data-tw-surface
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
className,
|
|
37
|
-
)}
|
|
33
|
+
tone="success"
|
|
34
|
+
className={className}
|
|
38
35
|
/>
|
|
39
36
|
);
|
|
40
37
|
});
|