@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,4 +1,8 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import {
|
|
2
|
+
requestAgentSidebarOpen,
|
|
3
|
+
SIDEBAR_STATE_CHANGE_EVENT,
|
|
4
|
+
type AgentSidebarStateChangeDetail,
|
|
5
|
+
} from "@agent-native/core/client/agent-chat";
|
|
2
6
|
import {
|
|
3
7
|
agentNativePath,
|
|
4
8
|
appBasePath,
|
|
@@ -46,7 +50,6 @@ import {
|
|
|
46
50
|
IconBolt,
|
|
47
51
|
IconMessage,
|
|
48
52
|
IconExternalLink,
|
|
49
|
-
IconFolder,
|
|
50
53
|
IconMoodSmile,
|
|
51
54
|
} from "@tabler/icons-react";
|
|
52
55
|
import { useQuery, useQueryClient } from "@tanstack/react-query";
|
|
@@ -64,7 +67,11 @@ import { toast } from "sonner";
|
|
|
64
67
|
import { ClipsAvatar } from "@/components/clips-avatar";
|
|
65
68
|
import { EditableRecordingTitle } from "@/components/editable-recording-title";
|
|
66
69
|
import { EditorLayout } from "@/components/editor/editor-layout";
|
|
67
|
-
import {
|
|
70
|
+
import {
|
|
71
|
+
PageBreadcrumb,
|
|
72
|
+
PageHeader,
|
|
73
|
+
type PageBreadcrumbItem,
|
|
74
|
+
} from "@/components/library/page-header";
|
|
68
75
|
import {
|
|
69
76
|
BrowserDiagnosticsPanel,
|
|
70
77
|
isFullBrowserDiagnostics,
|
|
@@ -101,14 +108,6 @@ import {
|
|
|
101
108
|
ViewerTabsTrigger,
|
|
102
109
|
} from "@/components/player/viewer-controls";
|
|
103
110
|
import { StorageSetupCard } from "@/components/recorder/storage-setup-card";
|
|
104
|
-
import {
|
|
105
|
-
Breadcrumb,
|
|
106
|
-
BreadcrumbItem,
|
|
107
|
-
BreadcrumbLink,
|
|
108
|
-
BreadcrumbList,
|
|
109
|
-
BreadcrumbPage,
|
|
110
|
-
BreadcrumbSeparator,
|
|
111
|
-
} from "@/components/ui/breadcrumb";
|
|
112
111
|
import { Button } from "@/components/ui/button";
|
|
113
112
|
import {
|
|
114
113
|
DropdownMenuItem,
|
|
@@ -419,9 +418,35 @@ export function meta() {
|
|
|
419
418
|
return [{ title: enMessages.recordingRoute.pageTitle }];
|
|
420
419
|
}
|
|
421
420
|
|
|
422
|
-
type SidePanel = "transcript" | "comments" | "
|
|
421
|
+
type SidePanel = "transcript" | "comments" | "debug" | "settings";
|
|
423
422
|
type ToolbarPanel = Exclude<SidePanel, "comments">;
|
|
424
423
|
|
|
424
|
+
function useGlobalAgentSidebarOpen() {
|
|
425
|
+
const [open, setOpen] = useState(false);
|
|
426
|
+
|
|
427
|
+
useEffect(() => {
|
|
428
|
+
const handleStateChange = (event: Event) => {
|
|
429
|
+
const detail = (event as CustomEvent<AgentSidebarStateChangeDetail>)
|
|
430
|
+
.detail;
|
|
431
|
+
if (detail && typeof detail.open === "boolean") {
|
|
432
|
+
setOpen(detail.open);
|
|
433
|
+
}
|
|
434
|
+
};
|
|
435
|
+
|
|
436
|
+
window.addEventListener(SIDEBAR_STATE_CHANGE_EVENT, handleStateChange);
|
|
437
|
+
const mountedPanel = document.querySelector<HTMLElement>(
|
|
438
|
+
".agent-sidebar-panel[data-agent-sidebar-state='open']",
|
|
439
|
+
);
|
|
440
|
+
setOpen(Boolean(mountedPanel));
|
|
441
|
+
|
|
442
|
+
return () => {
|
|
443
|
+
window.removeEventListener(SIDEBAR_STATE_CHANGE_EVENT, handleStateChange);
|
|
444
|
+
};
|
|
445
|
+
}, []);
|
|
446
|
+
|
|
447
|
+
return open;
|
|
448
|
+
}
|
|
449
|
+
|
|
425
450
|
const WORKFLOW_MENU_ITEMS: Array<{
|
|
426
451
|
kind: WorkflowKind;
|
|
427
452
|
labelKey: string;
|
|
@@ -536,6 +561,7 @@ export default function RecordingPage() {
|
|
|
536
561
|
const commentsSectionRef = useRef<HTMLElement | null>(null);
|
|
537
562
|
|
|
538
563
|
const [panel, setPanel] = useState<SidePanel | null>("transcript");
|
|
564
|
+
const globalAgentSidebarOpen = useGlobalAgentSidebarOpen();
|
|
539
565
|
const [theaterMode, setTheaterMode] = useState(false);
|
|
540
566
|
const [editing, setEditing] = useState(false);
|
|
541
567
|
const [currentMs, setCurrentMs] = useState(startMs);
|
|
@@ -573,16 +599,18 @@ export default function RecordingPage() {
|
|
|
573
599
|
const nextParams = new URLSearchParams(searchParams);
|
|
574
600
|
nextParams.set("panel", "comments");
|
|
575
601
|
setSearchParams(nextParams, { replace: true });
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
602
|
+
if (isCompactLayout) {
|
|
603
|
+
requestAnimationFrame(() => {
|
|
604
|
+
commentsSectionRef.current?.scrollIntoView({
|
|
605
|
+
block: "start",
|
|
606
|
+
behavior: "smooth",
|
|
607
|
+
});
|
|
580
608
|
});
|
|
581
|
-
}
|
|
582
|
-
}, [searchParams, setSearchParams]);
|
|
609
|
+
}
|
|
610
|
+
}, [isCompactLayout, searchParams, setSearchParams]);
|
|
583
611
|
const openAgentPanel = useCallback(() => {
|
|
584
|
-
|
|
585
|
-
}, [
|
|
612
|
+
requestAgentSidebarOpen();
|
|
613
|
+
}, []);
|
|
586
614
|
const transcriptKickedRef = useRef<string | null>(null);
|
|
587
615
|
// When the recording lands in the processing state but never flips to
|
|
588
616
|
// 'ready', stop spinning forever and surface an error banner so the user
|
|
@@ -929,17 +957,23 @@ export default function RecordingPage() {
|
|
|
929
957
|
}, [browserDiagnostics, canEdit, panel]);
|
|
930
958
|
|
|
931
959
|
useEffect(() => {
|
|
960
|
+
if (panelParam === "agent") {
|
|
961
|
+
setPanel("transcript");
|
|
962
|
+
requestAgentSidebarOpen();
|
|
963
|
+
return;
|
|
964
|
+
}
|
|
932
965
|
if (panelParam === "comments") {
|
|
933
|
-
setPanel("comments");
|
|
934
|
-
|
|
935
|
-
|
|
936
|
-
|
|
966
|
+
setPanel(recording?.enableComments ? "comments" : "transcript");
|
|
967
|
+
if (isCompactLayout) {
|
|
968
|
+
requestAnimationFrame(() => {
|
|
969
|
+
commentsSectionRef.current?.scrollIntoView({ block: "start" });
|
|
970
|
+
});
|
|
971
|
+
}
|
|
937
972
|
return;
|
|
938
973
|
}
|
|
939
974
|
if (
|
|
940
975
|
(panelParam === "transcript" ||
|
|
941
976
|
panelParam === "insights" ||
|
|
942
|
-
panelParam === "agent" ||
|
|
943
977
|
panelParam === "debug" ||
|
|
944
978
|
panelParam === "settings") &&
|
|
945
979
|
(panelParam !== "settings" || canEdit) &&
|
|
@@ -947,7 +981,13 @@ export default function RecordingPage() {
|
|
|
947
981
|
) {
|
|
948
982
|
setPanel(panelParam === "insights" ? "transcript" : panelParam);
|
|
949
983
|
}
|
|
950
|
-
}, [
|
|
984
|
+
}, [
|
|
985
|
+
browserDiagnostics,
|
|
986
|
+
canEdit,
|
|
987
|
+
isCompactLayout,
|
|
988
|
+
panelParam,
|
|
989
|
+
recording?.enableComments,
|
|
990
|
+
]);
|
|
951
991
|
|
|
952
992
|
const builderCredits =
|
|
953
993
|
(playerDataQ.data?.builderCredits as BuilderCreditsStatus | null) ?? null;
|
|
@@ -965,55 +1005,30 @@ export default function RecordingPage() {
|
|
|
965
1005
|
const visibleTitle = recording
|
|
966
1006
|
? displayRecordingTitle(recording.title)
|
|
967
1007
|
: "Untitled Clip";
|
|
1008
|
+
const recordingBreadcrumbItems: PageBreadcrumbItem[] = [
|
|
1009
|
+
...(recordingSpace
|
|
1010
|
+
? [
|
|
1011
|
+
{ label: t("navigation.spaces"), to: "/spaces" },
|
|
1012
|
+
{
|
|
1013
|
+
label: recordingSpace.name,
|
|
1014
|
+
to: `/spaces/${recordingSpace.id}`,
|
|
1015
|
+
},
|
|
1016
|
+
]
|
|
1017
|
+
: [{ label: t("navigation.library"), to: "/library" }]),
|
|
1018
|
+
...(recordingFolder
|
|
1019
|
+
? [
|
|
1020
|
+
{
|
|
1021
|
+
label: recordingFolder.name,
|
|
1022
|
+
to: recordingFolder.spaceId
|
|
1023
|
+
? `/spaces/${recordingFolder.spaceId}/folder/${recordingFolder.id}`
|
|
1024
|
+
: `/library/folder/${recordingFolder.id}`,
|
|
1025
|
+
},
|
|
1026
|
+
]
|
|
1027
|
+
: []),
|
|
1028
|
+
{ label: visibleTitle },
|
|
1029
|
+
];
|
|
968
1030
|
const recordingBreadcrumb = (
|
|
969
|
-
<
|
|
970
|
-
<BreadcrumbList className="flex-nowrap overflow-hidden">
|
|
971
|
-
<BreadcrumbItem className="shrink-0">
|
|
972
|
-
<BreadcrumbLink asChild>
|
|
973
|
-
<NavLink to="/library">{t("navigation.library")}</NavLink>
|
|
974
|
-
</BreadcrumbLink>
|
|
975
|
-
</BreadcrumbItem>
|
|
976
|
-
{recordingSpace ? (
|
|
977
|
-
<>
|
|
978
|
-
<BreadcrumbSeparator className="shrink-0" />
|
|
979
|
-
<BreadcrumbItem className="min-w-0">
|
|
980
|
-
<BreadcrumbLink asChild>
|
|
981
|
-
<NavLink
|
|
982
|
-
to={`/spaces/${recordingSpace.id}`}
|
|
983
|
-
className="truncate"
|
|
984
|
-
>
|
|
985
|
-
{recordingSpace.name}
|
|
986
|
-
</NavLink>
|
|
987
|
-
</BreadcrumbLink>
|
|
988
|
-
</BreadcrumbItem>
|
|
989
|
-
</>
|
|
990
|
-
) : null}
|
|
991
|
-
{recordingFolder ? (
|
|
992
|
-
<>
|
|
993
|
-
<BreadcrumbSeparator className="shrink-0" />
|
|
994
|
-
<BreadcrumbItem className="min-w-0">
|
|
995
|
-
<BreadcrumbLink asChild>
|
|
996
|
-
<NavLink
|
|
997
|
-
to={
|
|
998
|
-
recordingFolder.spaceId
|
|
999
|
-
? `/spaces/${recordingFolder.spaceId}/folder/${recordingFolder.id}`
|
|
1000
|
-
: `/library/folder/${recordingFolder.id}`
|
|
1001
|
-
}
|
|
1002
|
-
className="flex min-w-0 items-center gap-1.5"
|
|
1003
|
-
>
|
|
1004
|
-
<IconFolder className="size-4 shrink-0" />
|
|
1005
|
-
<span className="truncate">{recordingFolder.name}</span>
|
|
1006
|
-
</NavLink>
|
|
1007
|
-
</BreadcrumbLink>
|
|
1008
|
-
</BreadcrumbItem>
|
|
1009
|
-
</>
|
|
1010
|
-
) : null}
|
|
1011
|
-
<BreadcrumbSeparator className="shrink-0" />
|
|
1012
|
-
<BreadcrumbItem className="min-w-0">
|
|
1013
|
-
<BreadcrumbPage className="truncate">{visibleTitle}</BreadcrumbPage>
|
|
1014
|
-
</BreadcrumbItem>
|
|
1015
|
-
</BreadcrumbList>
|
|
1016
|
-
</Breadcrumb>
|
|
1031
|
+
<PageBreadcrumb items={recordingBreadcrumbItems} />
|
|
1017
1032
|
);
|
|
1018
1033
|
// Attribution `via` must never point at someone who isn't the owner, so it
|
|
1019
1034
|
// is only tagged when the viewer is the owner (same rule as the share dialog).
|
|
@@ -1925,7 +1940,7 @@ export default function RecordingPage() {
|
|
|
1925
1940
|
|
|
1926
1941
|
const renderPanelTabs = () => (
|
|
1927
1942
|
<ViewerTabsList className="min-w-0 shrink-0 bg-sidebar">
|
|
1928
|
-
{
|
|
1943
|
+
{recording.enableComments ? (
|
|
1929
1944
|
<ViewerTabsTrigger value="comments">
|
|
1930
1945
|
{t("playerSettings.comments")}
|
|
1931
1946
|
</ViewerTabsTrigger>
|
|
@@ -1933,9 +1948,6 @@ export default function RecordingPage() {
|
|
|
1933
1948
|
<ViewerTabsTrigger value="transcript">
|
|
1934
1949
|
{t("recordingPage.transcript")}
|
|
1935
1950
|
</ViewerTabsTrigger>
|
|
1936
|
-
<ViewerTabsTrigger value="agent">
|
|
1937
|
-
{t("recordingPage.agent")}
|
|
1938
|
-
</ViewerTabsTrigger>
|
|
1939
1951
|
{browserDiagnostics ? (
|
|
1940
1952
|
<ViewerTabsTrigger value="debug">
|
|
1941
1953
|
<span className="flex items-center justify-center gap-1.5">
|
|
@@ -1964,7 +1976,7 @@ export default function RecordingPage() {
|
|
|
1964
1976
|
"scroll-mt-14",
|
|
1965
1977
|
compact
|
|
1966
1978
|
? "flex min-h-0 flex-1 flex-col px-4 pb-5 pt-4"
|
|
1967
|
-
: "flex min-h-0 flex-1 flex-col px-
|
|
1979
|
+
: "flex min-h-0 flex-1 flex-col overflow-hidden px-3 pb-3 pt-3",
|
|
1968
1980
|
)}
|
|
1969
1981
|
>
|
|
1970
1982
|
{!compact ? (
|
|
@@ -1992,9 +2004,18 @@ export default function RecordingPage() {
|
|
|
1992
2004
|
</section>
|
|
1993
2005
|
);
|
|
1994
2006
|
|
|
1995
|
-
const renderSidePanel = () => {
|
|
2007
|
+
const renderSidePanel = (compact = false) => {
|
|
1996
2008
|
return (
|
|
1997
2009
|
<>
|
|
2010
|
+
{recording.enableComments ? (
|
|
2011
|
+
<TabsContent
|
|
2012
|
+
forceMount
|
|
2013
|
+
value="comments"
|
|
2014
|
+
className="mt-0 flex min-h-0 flex-1 flex-col overflow-hidden data-[state=inactive]:hidden"
|
|
2015
|
+
>
|
|
2016
|
+
{renderCommentsSection(compact)}
|
|
2017
|
+
</TabsContent>
|
|
2018
|
+
) : null}
|
|
1998
2019
|
<TabsContent
|
|
1999
2020
|
value="transcript"
|
|
2000
2021
|
className="mt-0 flex-1 min-h-0 data-[state=inactive]:hidden"
|
|
@@ -2035,26 +2056,6 @@ export default function RecordingPage() {
|
|
|
2035
2056
|
isRegenerating={requestTranscript.isPending}
|
|
2036
2057
|
/>
|
|
2037
2058
|
</TabsContent>
|
|
2038
|
-
<TabsContent
|
|
2039
|
-
value="agent"
|
|
2040
|
-
className="mt-0 flex min-h-0 flex-1 flex-col overflow-y-auto data-[state=inactive]:hidden"
|
|
2041
|
-
>
|
|
2042
|
-
<AgentPanel
|
|
2043
|
-
emptyStateText={t("recordingPage.askAboutClip")}
|
|
2044
|
-
dynamicSuggestions={false}
|
|
2045
|
-
scope={{ type: "recording", id: recording.id }}
|
|
2046
|
-
missingApiKeySetupLayout="sidebar"
|
|
2047
|
-
suggestions={[
|
|
2048
|
-
t("recordingPage.summarizeClip"),
|
|
2049
|
-
t("recordingPage.findKeyMoments"),
|
|
2050
|
-
t("recordingPage.listFollowUpActions"),
|
|
2051
|
-
t("recordingPage.draftQuestions"),
|
|
2052
|
-
]}
|
|
2053
|
-
browserTabId={browserTabId}
|
|
2054
|
-
showHeader={false}
|
|
2055
|
-
showTabBar={false}
|
|
2056
|
-
/>
|
|
2057
|
-
</TabsContent>
|
|
2058
2059
|
{browserDiagnostics ? (
|
|
2059
2060
|
<TabsContent
|
|
2060
2061
|
value="debug"
|
|
@@ -2392,7 +2393,7 @@ export default function RecordingPage() {
|
|
|
2392
2393
|
}
|
|
2393
2394
|
openSidePanel(value as ToolbarPanel);
|
|
2394
2395
|
}}
|
|
2395
|
-
className="clips-recording-view grid h-full min-h-0 w-full max-w-full grid-cols-1 overflow-x-hidden bg-background lg:grid-cols-[minmax(0,1fr)_auto] lg:grid-rows-[minmax(0,1fr)] lg:overflow-hidden
|
|
2396
|
+
className="clips-recording-view grid h-full min-h-0 w-full max-w-full grid-cols-1 overflow-x-hidden bg-background lg:grid-cols-[minmax(0,1fr)_auto] lg:grid-rows-[minmax(0,1fr)] lg:overflow-hidden"
|
|
2396
2397
|
>
|
|
2397
2398
|
{/* Main video column */}
|
|
2398
2399
|
<div className="contents">
|
|
@@ -2407,11 +2408,11 @@ export default function RecordingPage() {
|
|
|
2407
2408
|
{editing && canUseNativeEditor ? (
|
|
2408
2409
|
<EditorLayout recordingId={recording.id} className="flex-1" />
|
|
2409
2410
|
) : (
|
|
2410
|
-
<div className="mx-auto flex min-h-0 w-full flex-1 flex-col gap-0 sm:gap-4 lg:max-w-[calc(177.778dvh-35.556rem)]">
|
|
2411
|
+
<div className="mx-auto flex min-h-0 w-full flex-1 flex-col gap-0 sm:gap-4 lg:max-w-[min(100%,1600px,calc(177.778dvh-35.556rem))]">
|
|
2411
2412
|
<div className="flex w-full shrink-0 justify-center">
|
|
2412
|
-
{/*
|
|
2413
|
-
|
|
2414
|
-
|
|
2413
|
+
{/* Let the viewer grow on wide displays without pushing the
|
|
2414
|
+
discussion below the first scrollable viewport. The comments
|
|
2415
|
+
list owns the desktop scroll so the player stays in context. */}
|
|
2415
2416
|
<div className="relative aspect-video w-full overflow-hidden bg-card shadow-sm ring-1 ring-border sm:rounded-2xl">
|
|
2416
2417
|
<VideoPlayer
|
|
2417
2418
|
ref={playerRef}
|
|
@@ -2479,7 +2480,7 @@ export default function RecordingPage() {
|
|
|
2479
2480
|
onDraftChange={setCommentDraft}
|
|
2480
2481
|
onClose={() => setCommentOpen(false)}
|
|
2481
2482
|
onAdded={() => {
|
|
2482
|
-
setPanel("comments");
|
|
2483
|
+
if (isCompactLayout) setPanel("comments");
|
|
2483
2484
|
void playerDataQ.refetch();
|
|
2484
2485
|
}}
|
|
2485
2486
|
/>
|
|
@@ -2588,26 +2589,22 @@ export default function RecordingPage() {
|
|
|
2588
2589
|
</div>
|
|
2589
2590
|
</div>
|
|
2590
2591
|
|
|
2591
|
-
{isCompactLayout ? (
|
|
2592
|
+
{isCompactLayout && !globalAgentSidebarOpen ? (
|
|
2592
2593
|
<RecordingSidePanel
|
|
2593
2594
|
id="clip-activity-panel"
|
|
2594
2595
|
className="mt-2 lg:hidden"
|
|
2595
2596
|
tabs={renderPanelTabs()}
|
|
2596
2597
|
>
|
|
2597
|
-
{
|
|
2598
|
-
? renderCommentsSection(true)
|
|
2599
|
-
: renderSidePanel()}
|
|
2598
|
+
{renderSidePanel(true)}
|
|
2600
2599
|
</RecordingSidePanel>
|
|
2601
|
-
) :
|
|
2602
|
-
renderCommentsSection()
|
|
2603
|
-
)}
|
|
2600
|
+
) : null}
|
|
2604
2601
|
</div>
|
|
2605
2602
|
)}
|
|
2606
2603
|
</div>
|
|
2607
2604
|
</div>
|
|
2608
2605
|
|
|
2609
2606
|
{/* Side panel */}
|
|
2610
|
-
{!editing && !isCompactLayout &&
|
|
2607
|
+
{!editing && !isCompactLayout && !globalAgentSidebarOpen && panel ? (
|
|
2611
2608
|
<RecordingSidePanel
|
|
2612
2609
|
className="hidden lg:col-start-2 lg:row-start-1 lg:flex lg:w-[360px] xl:w-[420px] 2xl:w-[440px]"
|
|
2613
2610
|
tabs={renderPanelTabs()}
|
|
@@ -3,7 +3,8 @@ import { useMemo } from "react";
|
|
|
3
3
|
import { useParams } from "react-router";
|
|
4
4
|
|
|
5
5
|
import { LibraryGrid } from "@/components/library/library-grid";
|
|
6
|
-
import {
|
|
6
|
+
import { LibraryPrimaryActions } from "@/components/library/library-primary-actions";
|
|
7
|
+
import { useFolders, useOrganizations, useSpaces } from "@/hooks/use-library";
|
|
7
8
|
import enMessages from "@/i18n/en-US";
|
|
8
9
|
|
|
9
10
|
export function meta() {
|
|
@@ -17,7 +18,18 @@ export default function SpaceFolderRoute() {
|
|
|
17
18
|
folderId: string;
|
|
18
19
|
}>();
|
|
19
20
|
|
|
20
|
-
const { data:
|
|
21
|
+
const { data: organizations } = useOrganizations();
|
|
22
|
+
const currentOrganizationId =
|
|
23
|
+
organizations?.currentId ?? organizations?.organizations?.[0]?.id;
|
|
24
|
+
const { data: spacesData } = useSpaces(currentOrganizationId);
|
|
25
|
+
const space = (spacesData?.spaces ?? []).find(
|
|
26
|
+
(candidate: any) => candidate.id === spaceId,
|
|
27
|
+
);
|
|
28
|
+
|
|
29
|
+
const { data: folders } = useFolders({
|
|
30
|
+
organizationId: currentOrganizationId,
|
|
31
|
+
spaceId,
|
|
32
|
+
});
|
|
21
33
|
const folder = useMemo(
|
|
22
34
|
() =>
|
|
23
35
|
(folders?.folders ?? []).find((f: any) => f.id === folderId) as
|
|
@@ -33,6 +45,17 @@ export default function SpaceFolderRoute() {
|
|
|
33
45
|
folderId={folderId}
|
|
34
46
|
emptyKind="folder"
|
|
35
47
|
title={folder?.name ?? t("navigation.folder")}
|
|
48
|
+
breadcrumbItems={[
|
|
49
|
+
{ label: t("navigation.spaces"), to: "/spaces" },
|
|
50
|
+
{
|
|
51
|
+
label: space?.name ?? t("navigation.space"),
|
|
52
|
+
to: `/spaces/${spaceId}`,
|
|
53
|
+
},
|
|
54
|
+
{ label: folder?.name ?? t("navigation.folder") },
|
|
55
|
+
]}
|
|
56
|
+
extraActions={
|
|
57
|
+
<LibraryPrimaryActions folderId={folderId} spaceId={spaceId} />
|
|
58
|
+
}
|
|
36
59
|
/>
|
|
37
60
|
);
|
|
38
61
|
}
|
|
@@ -1,10 +1,9 @@
|
|
|
1
1
|
import { useT } from "@agent-native/core/client/i18n";
|
|
2
|
-
import { useMemo } from "react";
|
|
3
2
|
import { useParams } from "react-router";
|
|
4
3
|
|
|
5
|
-
import { FolderTree, type FolderNode } from "@/components/library/folder-tree";
|
|
6
4
|
import { LibraryGrid } from "@/components/library/library-grid";
|
|
7
|
-
import {
|
|
5
|
+
import { LibraryPrimaryActions } from "@/components/library/library-primary-actions";
|
|
6
|
+
import { useSpaces, useOrganizations } from "@/hooks/use-library";
|
|
8
7
|
import enMessages from "@/i18n/en-US";
|
|
9
8
|
|
|
10
9
|
export function meta() {
|
|
@@ -20,64 +19,18 @@ export default function SpaceRoute() {
|
|
|
20
19
|
const { data: spacesData } = useSpaces(currentOrganizationId);
|
|
21
20
|
const space = (spacesData?.spaces ?? []).find((s: any) => s.id === spaceId);
|
|
22
21
|
|
|
23
|
-
const { data: folders } = useFolders({
|
|
24
|
-
organizationId: currentOrganizationId,
|
|
25
|
-
spaceId,
|
|
26
|
-
});
|
|
27
|
-
const folderList: FolderNode[] = useMemo(
|
|
28
|
-
() =>
|
|
29
|
-
(folders?.folders ?? [])
|
|
30
|
-
.filter((f: any) => f.spaceId === spaceId)
|
|
31
|
-
.map((f: any) => ({
|
|
32
|
-
id: f.id,
|
|
33
|
-
parentId: f.parentId ?? null,
|
|
34
|
-
spaceId: f.spaceId ?? null,
|
|
35
|
-
name: f.name,
|
|
36
|
-
})),
|
|
37
|
-
[folders, spaceId],
|
|
38
|
-
);
|
|
39
|
-
|
|
40
22
|
return (
|
|
41
|
-
<
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
</div>
|
|
54
|
-
<span className="text-xs font-semibold text-foreground truncate">
|
|
55
|
-
{(space as any)?.name ?? t("navigation.space")}
|
|
56
|
-
</span>
|
|
57
|
-
</div>
|
|
58
|
-
</div>
|
|
59
|
-
<div className="mt-2">
|
|
60
|
-
<div className="px-2 pb-1 text-[10px] font-semibold uppercase tracking-wide text-muted-foreground">
|
|
61
|
-
{t("navigation.folders")}
|
|
62
|
-
</div>
|
|
63
|
-
<FolderTree
|
|
64
|
-
folders={folderList}
|
|
65
|
-
organizationId={currentOrganizationId}
|
|
66
|
-
spaceId={spaceId ?? null}
|
|
67
|
-
buildPath={(id) => `/spaces/${spaceId}/folder/${id}`}
|
|
68
|
-
/>
|
|
69
|
-
</div>
|
|
70
|
-
</aside>
|
|
71
|
-
|
|
72
|
-
<div className="flex min-w-0 flex-1 flex-col">
|
|
73
|
-
<LibraryGrid
|
|
74
|
-
view="space"
|
|
75
|
-
spaceId={spaceId}
|
|
76
|
-
folderId={null}
|
|
77
|
-
emptyKind="space"
|
|
78
|
-
title={(space as any)?.name ?? t("navigation.space")}
|
|
79
|
-
/>
|
|
80
|
-
</div>
|
|
81
|
-
</div>
|
|
23
|
+
<LibraryGrid
|
|
24
|
+
view="space"
|
|
25
|
+
spaceId={spaceId}
|
|
26
|
+
folderId={null}
|
|
27
|
+
emptyKind="space"
|
|
28
|
+
title={(space as any)?.name ?? t("navigation.space")}
|
|
29
|
+
breadcrumbItems={[
|
|
30
|
+
{ label: t("navigation.spaces"), to: "/spaces" },
|
|
31
|
+
{ label: (space as any)?.name ?? t("navigation.space") },
|
|
32
|
+
]}
|
|
33
|
+
extraActions={<LibraryPrimaryActions spaceId={spaceId} />}
|
|
34
|
+
/>
|
|
82
35
|
);
|
|
83
36
|
}
|
|
@@ -1,24 +1,20 @@
|
|
|
1
1
|
import { useT } from "@agent-native/core/client/i18n";
|
|
2
2
|
import { useOrgRole } from "@agent-native/core/client/org";
|
|
3
3
|
import { IconPlus, IconUsersGroup } from "@tabler/icons-react";
|
|
4
|
-
import { useState } from "react";
|
|
4
|
+
import { useEffect, useState } from "react";
|
|
5
5
|
|
|
6
6
|
import { CreateSpaceDialog } from "@/components/library/create-space-dialog";
|
|
7
|
+
import { AppEmptyState } from "@/components/library/empty-state";
|
|
7
8
|
import {
|
|
8
9
|
PageBreadcrumb,
|
|
9
10
|
PageHeader,
|
|
10
11
|
PageHeaderPrimaryAction,
|
|
11
12
|
} from "@/components/library/page-header";
|
|
12
13
|
import { SpaceCard, type SpaceCardData } from "@/components/library/space-card";
|
|
13
|
-
import {
|
|
14
|
-
Empty,
|
|
15
|
-
EmptyDescription,
|
|
16
|
-
EmptyHeader,
|
|
17
|
-
EmptyMedia,
|
|
18
|
-
EmptyTitle,
|
|
19
|
-
} from "@/components/ui/empty";
|
|
14
|
+
import { Button } from "@/components/ui/button";
|
|
20
15
|
import { useSpaces, useOrganizations } from "@/hooks/use-library";
|
|
21
16
|
import enMessages from "@/i18n/en-US";
|
|
17
|
+
import { OPEN_CREATE_SPACE_EVENT } from "@/lib/command-events";
|
|
22
18
|
|
|
23
19
|
export function meta() {
|
|
24
20
|
return [{ title: enMessages.clipsFinalRaw.spacesPageTitle }];
|
|
@@ -44,6 +40,18 @@ export default function SpacesIndexRoute() {
|
|
|
44
40
|
const currentOrganizationId =
|
|
45
41
|
organizations?.currentId ?? organizations?.organizations?.[0]?.id;
|
|
46
42
|
const { data, isLoading, refetch } = useSpaces(currentOrganizationId);
|
|
43
|
+
const createSpaceLabel = t("createSpaceDialog.newSpace");
|
|
44
|
+
|
|
45
|
+
useEffect(() => {
|
|
46
|
+
if (!canManageOrg) return;
|
|
47
|
+
const handleOpenCreateSpace = () => setCreateOpen(true);
|
|
48
|
+
window.addEventListener(OPEN_CREATE_SPACE_EVENT, handleOpenCreateSpace);
|
|
49
|
+
return () =>
|
|
50
|
+
window.removeEventListener(
|
|
51
|
+
OPEN_CREATE_SPACE_EVENT,
|
|
52
|
+
handleOpenCreateSpace,
|
|
53
|
+
);
|
|
54
|
+
}, [canManageOrg]);
|
|
47
55
|
|
|
48
56
|
const spaces: SpaceCardData[] = (data?.spaces ?? []).map((s: any) => ({
|
|
49
57
|
id: s.id,
|
|
@@ -58,12 +66,12 @@ export default function SpacesIndexRoute() {
|
|
|
58
66
|
return (
|
|
59
67
|
<div className="flex flex-1 flex-col min-h-0">
|
|
60
68
|
<PageHeader>
|
|
61
|
-
<PageBreadcrumb
|
|
62
|
-
{canManageOrg && (
|
|
69
|
+
<PageBreadcrumb items={[{ label: t("navigation.spaces") }]} />
|
|
70
|
+
{canManageOrg && spaces.length > 0 && (
|
|
63
71
|
<div className="ml-auto">
|
|
64
72
|
<PageHeaderPrimaryAction onClick={() => setCreateOpen(true)}>
|
|
65
73
|
<IconPlus />
|
|
66
|
-
{
|
|
74
|
+
{createSpaceLabel}
|
|
67
75
|
</PageHeaderPrimaryAction>
|
|
68
76
|
</div>
|
|
69
77
|
)}
|
|
@@ -77,19 +85,21 @@ export default function SpacesIndexRoute() {
|
|
|
77
85
|
))}
|
|
78
86
|
</div>
|
|
79
87
|
) : spaces.length === 0 ? (
|
|
80
|
-
<
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
88
|
+
<AppEmptyState
|
|
89
|
+
icon={IconUsersGroup}
|
|
90
|
+
title={t("navigation.noSpaces")}
|
|
91
|
+
description={
|
|
92
|
+
canManageOrg ? t("createSpaceDialog.description") : undefined
|
|
93
|
+
}
|
|
94
|
+
content={
|
|
95
|
+
canManageOrg ? (
|
|
96
|
+
<Button onClick={() => setCreateOpen(true)} size="sm">
|
|
97
|
+
<IconPlus />
|
|
98
|
+
{createSpaceLabel}
|
|
99
|
+
</Button>
|
|
100
|
+
) : null
|
|
101
|
+
}
|
|
102
|
+
/>
|
|
93
103
|
) : (
|
|
94
104
|
<div className="grid gap-4 [grid-template-columns:repeat(auto-fill,minmax(240px,1fr))]">
|
|
95
105
|
{spaces.map((s) => (
|
|
@@ -190,7 +190,7 @@ export default function TrashRoute() {
|
|
|
190
190
|
return (
|
|
191
191
|
<div className="flex flex-1 flex-col min-h-0">
|
|
192
192
|
<PageHeader>
|
|
193
|
-
<PageBreadcrumb
|
|
193
|
+
<PageBreadcrumb items={[{ label: t("trashRoute.title") }]} />
|
|
194
194
|
<div className="ms-auto flex items-center gap-2">
|
|
195
195
|
{selectedIds.length > 0 && (
|
|
196
196
|
<>
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { useExperiment } from "@agent-native/core/client/experiments";
|
|
2
2
|
import { CLIPS_MEETINGS, CLIPS_WISPRFLOW } from "@shared/experiments";
|
|
3
3
|
import { useEffect, useRef } from "react";
|
|
4
|
-
import { Outlet,
|
|
4
|
+
import { Outlet, useNavigate } from "react-router";
|
|
5
5
|
|
|
6
6
|
import { LibraryLayout } from "@/components/library/library-layout";
|
|
7
7
|
import { useAutoTitleBridge } from "@/hooks/use-auto-title";
|
|
@@ -71,8 +71,6 @@ function useGlobalSequenceShortcuts() {
|
|
|
71
71
|
// Pathless layout route — keeps the left sidebar + agent chat mounted across
|
|
72
72
|
// every library/space/archive/trash navigation. See client-side-routing skill.
|
|
73
73
|
export default function AppLayoutRoute() {
|
|
74
|
-
const location = useLocation();
|
|
75
|
-
const recordingWorkspace = /^\/r\/[^/]+\/?$/.test(location.pathname);
|
|
76
74
|
// Watch for server-queued title delegations and dispatch them to the agent
|
|
77
75
|
// chat. `sendToAgentChat` is browser-only so the server can't call it
|
|
78
76
|
// directly; this bridge is how `request-transcript`'s "auto-title when the
|
|
@@ -83,7 +81,7 @@ export default function AppLayoutRoute() {
|
|
|
83
81
|
useGlobalSequenceShortcuts();
|
|
84
82
|
|
|
85
83
|
return (
|
|
86
|
-
<LibraryLayout
|
|
84
|
+
<LibraryLayout>
|
|
87
85
|
<Outlet />
|
|
88
86
|
</LibraryLayout>
|
|
89
87
|
);
|