@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
|
@@ -6,7 +6,8 @@ import {
|
|
|
6
6
|
IconArchive,
|
|
7
7
|
IconTrash,
|
|
8
8
|
} from "@tabler/icons-react";
|
|
9
|
-
import {
|
|
9
|
+
import type { ComponentType, ReactNode } from "react";
|
|
10
|
+
import { Link, useNavigate } from "react-router";
|
|
10
11
|
|
|
11
12
|
import { Button } from "@/components/ui/button";
|
|
12
13
|
import {
|
|
@@ -38,6 +39,40 @@ const ICONS: Record<EmptyKind, React.ComponentType<{ className?: string }>> = {
|
|
|
38
39
|
};
|
|
39
40
|
|
|
40
41
|
const CTA_KINDS = new Set<EmptyKind>(["library", "folder", "space"]);
|
|
42
|
+
const BACK_TO_LIBRARY_KINDS = new Set<EmptyKind>([
|
|
43
|
+
"shared",
|
|
44
|
+
"archive",
|
|
45
|
+
"trash",
|
|
46
|
+
]);
|
|
47
|
+
|
|
48
|
+
interface AppEmptyStateProps {
|
|
49
|
+
icon: ComponentType<{ className?: string }>;
|
|
50
|
+
title: ReactNode;
|
|
51
|
+
description?: ReactNode;
|
|
52
|
+
content?: ReactNode;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
export function AppEmptyState({
|
|
56
|
+
icon: Icon,
|
|
57
|
+
title,
|
|
58
|
+
description,
|
|
59
|
+
content,
|
|
60
|
+
}: AppEmptyStateProps) {
|
|
61
|
+
return (
|
|
62
|
+
<Empty className="min-h-64 px-6 py-12 md:p-12">
|
|
63
|
+
<EmptyHeader>
|
|
64
|
+
<EmptyMedia variant="icon">
|
|
65
|
+
<Icon />
|
|
66
|
+
</EmptyMedia>
|
|
67
|
+
<EmptyTitle>{title}</EmptyTitle>
|
|
68
|
+
{description ? (
|
|
69
|
+
<EmptyDescription>{description}</EmptyDescription>
|
|
70
|
+
) : null}
|
|
71
|
+
</EmptyHeader>
|
|
72
|
+
{content ? <EmptyContent>{content}</EmptyContent> : null}
|
|
73
|
+
</Empty>
|
|
74
|
+
);
|
|
75
|
+
}
|
|
41
76
|
|
|
42
77
|
interface EmptyStateProps {
|
|
43
78
|
kind: EmptyKind;
|
|
@@ -69,22 +104,22 @@ export function EmptyState({
|
|
|
69
104
|
}
|
|
70
105
|
};
|
|
71
106
|
|
|
107
|
+
const content = hasCta ? (
|
|
108
|
+
<Button onClick={handleCta} size="sm">
|
|
109
|
+
{t(`empty.${kind}.cta`)}
|
|
110
|
+
</Button>
|
|
111
|
+
) : BACK_TO_LIBRARY_KINDS.has(kind) ? (
|
|
112
|
+
<Button asChild size="sm" variant="outline">
|
|
113
|
+
<Link to="/library">{t("recordingPage.backToLibrary")}</Link>
|
|
114
|
+
</Button>
|
|
115
|
+
) : null;
|
|
116
|
+
|
|
72
117
|
return (
|
|
73
|
-
<
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
<EmptyDescription>{t(`empty.${kind}.body`)}</EmptyDescription>
|
|
80
|
-
</EmptyHeader>
|
|
81
|
-
{hasCta ? (
|
|
82
|
-
<EmptyContent>
|
|
83
|
-
<Button onClick={handleCta} size="sm">
|
|
84
|
-
{t(`empty.${kind}.cta`)}
|
|
85
|
-
</Button>
|
|
86
|
-
</EmptyContent>
|
|
87
|
-
) : null}
|
|
88
|
-
</Empty>
|
|
118
|
+
<AppEmptyState
|
|
119
|
+
icon={Icon}
|
|
120
|
+
title={t(`empty.${kind}.title`)}
|
|
121
|
+
description={t(`empty.${kind}.body`)}
|
|
122
|
+
content={content}
|
|
123
|
+
/>
|
|
89
124
|
);
|
|
90
125
|
}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { useT } from "@agent-native/core/client/i18n";
|
|
2
|
+
import { IconFolderOpen } from "@tabler/icons-react";
|
|
3
|
+
import { Link } from "react-router";
|
|
4
|
+
|
|
5
|
+
import { cn } from "@/lib/utils";
|
|
6
|
+
|
|
7
|
+
interface FolderCardProps {
|
|
8
|
+
folder: {
|
|
9
|
+
id: string;
|
|
10
|
+
name: string;
|
|
11
|
+
};
|
|
12
|
+
href: string;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export function FolderCard({ folder, href }: FolderCardProps) {
|
|
16
|
+
const t = useT();
|
|
17
|
+
|
|
18
|
+
return (
|
|
19
|
+
<Link
|
|
20
|
+
to={href}
|
|
21
|
+
aria-label={`${folder.name} — ${t("navigation.folder")}`}
|
|
22
|
+
className={cn(
|
|
23
|
+
"group flex h-14 min-w-0 items-center gap-3 rounded-lg border border-border bg-card px-3.5 py-2.5 text-start",
|
|
24
|
+
"shadow-[0_1px_2px_rgba(15,23,42,0.04)] transition-colors hover:border-primary/40 hover:bg-accent/20",
|
|
25
|
+
"focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2",
|
|
26
|
+
)}
|
|
27
|
+
>
|
|
28
|
+
<IconFolderOpen className="size-5 shrink-0 text-muted-foreground transition-transform group-hover:scale-105 motion-reduce:transition-none" />
|
|
29
|
+
<span className="min-w-0 truncate text-sm font-medium text-foreground">
|
|
30
|
+
{folder.name}
|
|
31
|
+
</span>
|
|
32
|
+
</Link>
|
|
33
|
+
);
|
|
34
|
+
}
|
|
@@ -53,6 +53,7 @@ export interface FolderNode {
|
|
|
53
53
|
parentId: string | null;
|
|
54
54
|
spaceId: string | null;
|
|
55
55
|
name: string;
|
|
56
|
+
recordingCount?: number;
|
|
56
57
|
children?: FolderNode[];
|
|
57
58
|
}
|
|
58
59
|
|
|
@@ -80,6 +81,8 @@ interface FolderTreeProps {
|
|
|
80
81
|
/** Build the URL for a folder — allows library or space-scoped trees. */
|
|
81
82
|
buildPath: (folderId: string) => string;
|
|
82
83
|
activeFolderId?: string | null;
|
|
84
|
+
/** Use the single-indent spacing expected by a sidebar submenu. */
|
|
85
|
+
compact?: boolean;
|
|
83
86
|
}
|
|
84
87
|
|
|
85
88
|
export function FolderTree({
|
|
@@ -88,6 +91,7 @@ export function FolderTree({
|
|
|
88
91
|
spaceId = null,
|
|
89
92
|
buildPath,
|
|
90
93
|
activeFolderId,
|
|
94
|
+
compact = false,
|
|
91
95
|
}: FolderTreeProps) {
|
|
92
96
|
const t = useT();
|
|
93
97
|
const tree = useMemo(() => buildTree(folders), [folders]);
|
|
@@ -111,6 +115,7 @@ export function FolderTree({
|
|
|
111
115
|
activeFolderId={activeFolderId}
|
|
112
116
|
organizationId={organizationId}
|
|
113
117
|
spaceId={spaceId}
|
|
118
|
+
compact={compact}
|
|
114
119
|
/>
|
|
115
120
|
))}
|
|
116
121
|
</ul>
|
|
@@ -124,6 +129,7 @@ interface FolderItemProps {
|
|
|
124
129
|
activeFolderId?: string | null;
|
|
125
130
|
organizationId?: string;
|
|
126
131
|
spaceId?: string | null;
|
|
132
|
+
compact: boolean;
|
|
127
133
|
}
|
|
128
134
|
|
|
129
135
|
function FolderItem({
|
|
@@ -133,6 +139,7 @@ function FolderItem({
|
|
|
133
139
|
activeFolderId,
|
|
134
140
|
organizationId,
|
|
135
141
|
spaceId,
|
|
142
|
+
compact,
|
|
136
143
|
}: FolderItemProps) {
|
|
137
144
|
const t = useT();
|
|
138
145
|
const [open, setOpen] = useState(true);
|
|
@@ -159,85 +166,122 @@ function FolderItem({
|
|
|
159
166
|
"group flex items-center gap-1 rounded px-1.5 py-1 text-xs",
|
|
160
167
|
isActive
|
|
161
168
|
? "bg-primary/10 text-primary"
|
|
162
|
-
: "text-
|
|
169
|
+
: "text-primary hover:bg-accent/60",
|
|
163
170
|
)}
|
|
164
|
-
style={{
|
|
171
|
+
style={{
|
|
172
|
+
paddingInlineStart: compact ? 8 + depth * 12 : 6 + depth * 12,
|
|
173
|
+
}}
|
|
165
174
|
>
|
|
166
|
-
|
|
167
|
-
<
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
"rounded p-0.5 text-muted-foreground",
|
|
171
|
-
!hasChildren && "invisible",
|
|
172
|
-
)}
|
|
173
|
-
onClick={(e) => e.stopPropagation()}
|
|
174
|
-
aria-label={`${t(open ? "settings.collapse" : "settings.expand")}: ${node.name}`}
|
|
175
|
-
>
|
|
176
|
-
<IconChevronRight
|
|
175
|
+
{!compact && (
|
|
176
|
+
<CollapsibleTrigger asChild disabled={!hasChildren}>
|
|
177
|
+
<button
|
|
178
|
+
type="button"
|
|
177
179
|
className={cn(
|
|
178
|
-
"
|
|
179
|
-
|
|
180
|
+
"rounded p-0.5 text-primary",
|
|
181
|
+
!hasChildren && "invisible",
|
|
180
182
|
)}
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
183
|
+
onClick={(e) => e.stopPropagation()}
|
|
184
|
+
aria-label={`${t(open ? "settings.collapse" : "settings.expand")}: ${node.name}`}
|
|
185
|
+
>
|
|
186
|
+
<IconChevronRight
|
|
187
|
+
className={cn(
|
|
188
|
+
"h-3 w-3 transition-transform motion-reduce:transition-none rtl:-scale-x-100",
|
|
189
|
+
open && "rotate-90",
|
|
190
|
+
)}
|
|
191
|
+
/>
|
|
192
|
+
</button>
|
|
193
|
+
</CollapsibleTrigger>
|
|
194
|
+
)}
|
|
184
195
|
<NavLink
|
|
185
196
|
to={buildPath(node.id)}
|
|
186
|
-
className=
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
<IconFolderOpen className="h-3.5 w-3.5 shrink-0 text-muted-foreground" />
|
|
190
|
-
) : (
|
|
191
|
-
<IconFolder className="h-3.5 w-3.5 shrink-0 text-muted-foreground" />
|
|
197
|
+
className={cn(
|
|
198
|
+
"flex min-w-0 flex-1 items-center",
|
|
199
|
+
compact ? "gap-0" : "gap-1.5",
|
|
192
200
|
)}
|
|
201
|
+
>
|
|
202
|
+
{!compact &&
|
|
203
|
+
(open && hasChildren ? (
|
|
204
|
+
<IconFolderOpen className="h-3.5 w-3.5 shrink-0 text-primary" />
|
|
205
|
+
) : (
|
|
206
|
+
<IconFolder className="h-3.5 w-3.5 shrink-0 text-primary" />
|
|
207
|
+
))}
|
|
193
208
|
<span className="truncate" title={node.name}>
|
|
194
209
|
{node.name}
|
|
195
210
|
</span>
|
|
196
211
|
</NavLink>
|
|
197
|
-
|
|
198
|
-
<
|
|
212
|
+
{compact && hasChildren && (
|
|
213
|
+
<CollapsibleTrigger asChild>
|
|
199
214
|
<button
|
|
200
215
|
type="button"
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
216
|
+
className="rounded p-0.5 text-primary hover:bg-accent focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring"
|
|
217
|
+
onClick={(e) => e.stopPropagation()}
|
|
218
|
+
aria-label={`${t(open ? "settings.collapse" : "settings.expand")}: ${node.name}`}
|
|
204
219
|
>
|
|
205
|
-
<
|
|
220
|
+
<IconChevronRight
|
|
221
|
+
className={cn(
|
|
222
|
+
"h-3 w-3 transition-transform motion-reduce:transition-none rtl:-scale-x-100",
|
|
223
|
+
open && "rotate-90",
|
|
224
|
+
)}
|
|
225
|
+
/>
|
|
206
226
|
</button>
|
|
207
|
-
</
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
}
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
227
|
+
</CollapsibleTrigger>
|
|
228
|
+
)}
|
|
229
|
+
<div className="relative size-5 shrink-0">
|
|
230
|
+
<DropdownMenu>
|
|
231
|
+
<DropdownMenuTrigger asChild>
|
|
232
|
+
<button
|
|
233
|
+
type="button"
|
|
234
|
+
aria-label={`${node.name}: ${t("root.commandActions")}`}
|
|
235
|
+
title={`${node.name}: ${t("root.commandActions")}`}
|
|
236
|
+
className="peer absolute inset-0 flex items-center justify-center rounded text-primary opacity-0 transition-opacity hover:bg-accent hover:text-primary focus-visible:opacity-100 focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring group-hover:opacity-100 group-focus-within:opacity-100 data-[state=open]:opacity-100"
|
|
237
|
+
>
|
|
238
|
+
<IconDots className="h-3.5 w-3.5" />
|
|
239
|
+
</button>
|
|
240
|
+
</DropdownMenuTrigger>
|
|
241
|
+
<DropdownMenuContent align="start" side="right">
|
|
242
|
+
<DropdownMenuItem
|
|
243
|
+
onSelect={() => {
|
|
244
|
+
setTimeout(() => {
|
|
245
|
+
setRenameValue(node.name);
|
|
246
|
+
setRenameOpen(true);
|
|
247
|
+
}, 0);
|
|
248
|
+
}}
|
|
249
|
+
>
|
|
250
|
+
<IconEdit className="h-3.5 w-3.5 me-2" />{" "}
|
|
251
|
+
{t("folderTree.rename")}
|
|
252
|
+
</DropdownMenuItem>
|
|
253
|
+
<DropdownMenuItem
|
|
254
|
+
onSelect={() => {
|
|
255
|
+
setTimeout(() => {
|
|
256
|
+
setNewValue("");
|
|
257
|
+
setNewOpen(true);
|
|
258
|
+
}, 0);
|
|
259
|
+
}}
|
|
260
|
+
>
|
|
261
|
+
<IconFolderPlus className="h-3.5 w-3.5 me-2" />{" "}
|
|
262
|
+
{t("folderTree.newSubfolder")}
|
|
263
|
+
</DropdownMenuItem>
|
|
264
|
+
<DropdownMenuSeparator />
|
|
265
|
+
<DropdownMenuItem
|
|
266
|
+
onSelect={() =>
|
|
267
|
+
setTimeout(() => setConfirmDelete(true), 0)
|
|
268
|
+
}
|
|
269
|
+
className="text-destructive"
|
|
270
|
+
>
|
|
271
|
+
<IconTrash className="h-3.5 w-3.5 me-2" />{" "}
|
|
272
|
+
{t("folderTree.delete")}
|
|
273
|
+
</DropdownMenuItem>
|
|
274
|
+
</DropdownMenuContent>
|
|
275
|
+
</DropdownMenu>
|
|
276
|
+
{(node.recordingCount ?? 0) > 0 && (
|
|
277
|
+
<span className="pointer-events-none absolute inset-0 flex items-center justify-end tabular-nums text-[11px] text-primary/80 transition-opacity group-hover:opacity-0 group-focus-within:opacity-0 peer-data-[state=open]:opacity-0">
|
|
278
|
+
{node.recordingCount}
|
|
279
|
+
<span className="sr-only">
|
|
280
|
+
{t("navigation.recordings")}
|
|
281
|
+
</span>
|
|
282
|
+
</span>
|
|
283
|
+
)}
|
|
284
|
+
</div>
|
|
241
285
|
</div>
|
|
242
286
|
</ContextMenuTrigger>
|
|
243
287
|
<ContextMenuContent>
|
|
@@ -292,6 +336,7 @@ function FolderItem({
|
|
|
292
336
|
activeFolderId={activeFolderId}
|
|
293
337
|
organizationId={organizationId}
|
|
294
338
|
spaceId={spaceId}
|
|
339
|
+
compact={compact}
|
|
295
340
|
/>
|
|
296
341
|
))}
|
|
297
342
|
</ul>
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
export interface LibraryActionScope {
|
|
2
|
+
folderId?: string | null;
|
|
3
|
+
spaceId?: string | null;
|
|
4
|
+
}
|
|
5
|
+
|
|
6
|
+
function scopedPath(pathname: string, params: URLSearchParams) {
|
|
7
|
+
const query = params.toString();
|
|
8
|
+
return query ? `${pathname}?${query}` : pathname;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export function buildLibraryActionHrefs({
|
|
12
|
+
folderId,
|
|
13
|
+
spaceId,
|
|
14
|
+
}: LibraryActionScope) {
|
|
15
|
+
const scope = new URLSearchParams();
|
|
16
|
+
if (spaceId) scope.set("spaceId", spaceId);
|
|
17
|
+
if (folderId) scope.set("folderId", folderId);
|
|
18
|
+
|
|
19
|
+
const uploadParams = new URLSearchParams(scope);
|
|
20
|
+
uploadParams.set("autoUpload", "1");
|
|
21
|
+
|
|
22
|
+
return {
|
|
23
|
+
recordHref: scopedPath("/record", scope),
|
|
24
|
+
uploadHref: scopedPath("/record", uploadParams),
|
|
25
|
+
importLoomHref: scopedPath("/import", scope),
|
|
26
|
+
};
|
|
27
|
+
}
|