@agent-native/core 0.79.17 → 0.79.19
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 +2 -2
- package/corpus/core/CHANGELOG.md +14 -0
- package/corpus/core/docs/content/file-uploads.md +11 -4
- package/corpus/core/docs/content/locales/ar-SA/multi-app-workspace.md +3 -3
- package/corpus/core/docs/content/locales/de-DE/multi-app-workspace.md +3 -3
- package/corpus/core/docs/content/locales/es-ES/multi-app-workspace.md +3 -3
- package/corpus/core/docs/content/locales/fr-FR/multi-app-workspace.md +3 -3
- package/corpus/core/docs/content/locales/hi-IN/multi-app-workspace.md +3 -3
- package/corpus/core/docs/content/locales/ja-JP/multi-app-workspace.md +3 -3
- package/corpus/core/docs/content/locales/ko-KR/multi-app-workspace.md +3 -3
- package/corpus/core/docs/content/locales/pt-BR/multi-app-workspace.md +3 -3
- package/corpus/core/docs/content/locales/zh-CN/multi-app-workspace.md +3 -3
- package/corpus/core/docs/content/locales/zh-TW/multi-app-workspace.md +3 -3
- package/corpus/core/docs/content/multi-app-workspace.md +3 -3
- package/corpus/core/docs/content/template-clips.md +14 -5
- package/corpus/core/package.json +1 -1
- package/corpus/core/src/agent/engine/builder-engine.ts +8 -3
- package/corpus/core/src/cli/mcp.ts +11 -6
- package/corpus/core/src/client/AssistantChat.tsx +6 -2
- package/corpus/core/src/client/chat/markdown-renderer.tsx +1 -0
- package/corpus/core/src/client/i18n.tsx +77 -65
- package/corpus/core/src/client/index.ts +7 -1
- package/corpus/core/src/client/org/OrgSwitcher.tsx +5 -5
- package/corpus/core/src/client/org/TeamPage.tsx +11 -3
- package/corpus/core/src/client/settings/SettingsTabsPage.tsx +216 -0
- package/corpus/core/src/client/settings/index.ts +5 -0
- package/corpus/core/src/file-upload/index.ts +1 -0
- package/corpus/core/src/file-upload/registry.ts +22 -6
- package/corpus/core/src/file-upload/types.ts +6 -1
- package/corpus/core/src/integrations/adapters/email.ts +26 -18
- package/corpus/core/src/integrations/adapters/slack.ts +8 -7
- package/corpus/core/src/integrations/adapters/telegram.ts +9 -11
- package/corpus/core/src/integrations/adapters/whatsapp.ts +12 -9
- package/corpus/core/src/integrations/plugin.ts +79 -13
- package/corpus/core/src/onboarding/default-steps.ts +6 -3
- package/corpus/core/src/onboarding/types.ts +1 -1
- package/corpus/core/src/org/handlers.ts +1 -1
- package/corpus/core/src/server/agent-chat-plugin.ts +4 -7
- package/corpus/core/src/server/better-auth-instance.ts +19 -62
- package/corpus/core/src/server/core-routes-plugin.ts +93 -180
- package/corpus/core/src/server/create-server.ts +55 -116
- package/corpus/core/src/server/email-actions.ts +3 -6
- package/corpus/core/src/server/email.ts +52 -17
- package/corpus/core/src/server/index.ts +2 -1
- package/corpus/core/src/server/scoped-key-storage.ts +223 -0
- package/corpus/core/src/shared/agent-env.ts +3 -3
- package/corpus/core/src/sharing/actions/share-resource.ts +1 -1
- package/corpus/core/src/styles/agent-native.css +47 -3
- package/corpus/core/src/templates/workspace-root/AGENTS.md +3 -2
- package/corpus/core/src/templates/workspace-root/README.md +1 -1
- package/corpus/core/src/templates/workspace-root/scripts/repair-workspace-org.ts +29 -90
- package/corpus/core/src/terminal/pty-server.ts +3 -38
- package/corpus/core/src/triggers/dispatcher.ts +1 -2
- package/corpus/templates/.retired/issues/package.json +7 -0
- package/corpus/templates/.retired/meeting-notes/package.json +7 -0
- package/corpus/templates/.retired/recruiting/package.json +7 -0
- package/corpus/templates/.retired/scheduling/package.json +7 -0
- package/corpus/templates/.retired/voice/package.json +7 -0
- package/corpus/templates/analytics/app/components/layout/Header.tsx +0 -1
- package/corpus/templates/analytics/app/components/layout/Sidebar.tsx +1 -18
- package/corpus/templates/analytics/app/global.css +15 -0
- package/corpus/templates/analytics/app/i18n/zh-TW.ts +7 -1
- package/corpus/templates/analytics/app/i18n-data.ts +71 -2
- package/corpus/templates/analytics/app/pages/Ask.tsx +1 -1
- package/corpus/templates/analytics/app/pages/Settings.tsx +120 -73
- package/corpus/templates/analytics/app/pages/sessions/SessionsPage.tsx +0 -11
- package/corpus/templates/analytics/app/routes/catalog.tsx +33 -176
- package/corpus/templates/analytics/app/routes/team.tsx +3 -2
- package/corpus/templates/analytics/changelog/2026-06-26-dashboard-templates-are-tucked-into-settings-and-show-simple.md +6 -0
- package/corpus/templates/analytics/changelog/2026-06-26-the-ask-tab-uses-a-softer-dark-gray-canvas-while-sidebar-cha.md +6 -0
- package/corpus/templates/analytics/changelog/2026-06-26-the-sessions-page-shows-a-single-page-title-instead-of-repea.md +6 -0
- package/corpus/templates/analytics/server/lib/dashboard-catalog.ts +37 -28
- package/corpus/templates/assets/app/routes/settings.tsx +65 -43
- package/corpus/templates/assets/app/routes/team.tsx +2 -10
- package/corpus/templates/brain/app/routes/settings.tsx +390 -358
- package/corpus/templates/brain/app/routes/team.tsx +2 -8
- package/corpus/templates/calendar/actions/db-connect.ts +5 -29
- package/corpus/templates/calendar/app/components/CloudUpgrade.tsx +8 -51
- package/corpus/templates/calendar/app/components/calendar/GoogleConnectBanner.tsx +2 -1
- package/corpus/templates/calendar/app/components/calendar/GoogleSetupWizard.tsx +4 -2
- package/corpus/templates/calendar/app/components/layout/Sidebar.tsx +0 -2
- package/corpus/templates/calendar/app/pages/Settings.tsx +304 -271
- package/corpus/templates/calendar/app/routes/_app.team.tsx +2 -17
- package/corpus/templates/calendar/server/handlers/google-auth.ts +22 -9
- package/corpus/templates/calendar/server/lib/booking-emails.ts +1 -1
- package/corpus/templates/calendar/server/lib/event-guest-notifications.ts +1 -1
- package/corpus/templates/calendar/server/lib/google-calendar.ts +48 -28
- package/corpus/templates/chat/app/components/layout/Header.tsx +0 -1
- package/corpus/templates/chat/app/hooks/use-navigation-state.ts +4 -2
- package/corpus/templates/chat/app/routes/settings.tsx +54 -54
- package/corpus/templates/chat/app/routes/team.tsx +2 -10
- package/corpus/templates/clips/.agents/skills/ai-video-tools/SKILL.md +7 -2
- package/corpus/templates/clips/.agents/skills/recording/SKILL.md +1 -1
- package/corpus/templates/clips/.agents/skills/video-sharing/SKILL.md +7 -0
- package/corpus/templates/clips/AGENTS.md +8 -0
- package/corpus/templates/clips/actions/invite-member.ts +1 -1
- package/corpus/templates/clips/actions/request-transcript.ts +1 -1
- package/corpus/templates/clips/app/components/library/library-layout.tsx +325 -333
- package/corpus/templates/clips/app/components/player/delete-recording-menu.tsx +80 -40
- package/corpus/templates/clips/app/components/player/transcript-panel.tsx +2 -0
- package/corpus/templates/clips/app/routes/_app.settings._index.tsx +629 -643
- package/corpus/templates/clips/app/routes/r.$recordingId.tsx +263 -158
- package/corpus/templates/clips/app/routes/share.$shareId.tsx +10 -2
- package/corpus/templates/clips/changelog/2026-06-26-long-desktop-recordings-are-checkpointed-so-macos-finalizati.md +6 -0
- package/corpus/templates/clips/changelog/2026-06-26-non-mac-desktop-recordings-wait-for-upload-transcription.md +6 -0
- package/corpus/templates/clips/changelog/2026-06-26-recording-details-button-stays-at-the-far-right-on-small-screen.md +6 -0
- package/corpus/templates/clips/changelog/2026-06-26-s3-compatible-storage-keys-now-save-securely-from-clips-sett.md +6 -0
- package/corpus/templates/clips/changelog/2026-06-26-shared-clip-links-guide-agents-through-processing-transcripts.md +6 -0
- package/corpus/templates/clips/changelog/2026-06-26-the-agent-sidebar-now-slides-in-smoothly-without-duplicate-e.md +6 -0
- package/corpus/templates/clips/changelog/2026-06-26-the-clip-details-sidebar-now-collapses-into-a-slide-out-pane.md +6 -0
- package/corpus/templates/clips/desktop/src/lib/recorder.ts +55 -3
- package/corpus/templates/clips/desktop/src/lib/transcription-capture.ts +217 -5
- package/corpus/templates/clips/desktop/src-tauri/src/lib.rs +1 -0
- package/corpus/templates/clips/desktop/src-tauri/src/native_screen.rs +176 -5
- package/corpus/templates/clips/server/lib/public-agent-context.ts +31 -0
- package/corpus/templates/clips/server/lib/s3-upload-provider.ts +60 -14
- package/corpus/templates/clips/server/lib/video-storage.ts +37 -9
- package/corpus/templates/clips/server/routes/api/agent-transcript.json.get.ts +5 -0
- package/corpus/templates/content/app/components/layout/Header.tsx +0 -1
- package/corpus/templates/content/app/components/sidebar/NotionButton.tsx +1 -0
- package/corpus/templates/content/app/routes/_app.settings.tsx +54 -55
- package/corpus/templates/content/app/routes/_app.team.tsx +2 -28
- package/corpus/templates/content/server/lib/notion.ts +43 -11
- package/corpus/templates/content/server/routes/api/notion/auth-url.get.ts +2 -2
- package/corpus/templates/content/server/routes/api/notion/status.get.ts +3 -3
- package/corpus/templates/design/app/routes/settings.tsx +60 -38
- package/corpus/templates/design/app/routes/team.tsx +2 -10
- package/corpus/templates/dispatch/app/hooks/use-navigation-state.ts +2 -2
- package/corpus/templates/dispatch/app/routes/settings.tsx +70 -55
- package/corpus/templates/dispatch/app/routes/team.tsx +5 -1
- package/corpus/templates/forms/actions/db-connect.ts +7 -36
- package/corpus/templates/forms/actions/navigate.ts +2 -2
- package/corpus/templates/forms/app/components/CloudUpgrade.tsx +8 -47
- package/corpus/templates/forms/app/components/layout/Header.tsx +0 -1
- package/corpus/templates/forms/app/components/layout/Layout.tsx +42 -25
- package/corpus/templates/forms/app/components/layout/Sidebar.tsx +35 -76
- package/corpus/templates/forms/app/global.css +9 -25
- package/corpus/templates/forms/app/hooks/use-navigation-state.ts +4 -4
- package/corpus/templates/forms/app/i18n/ar-SA.ts +1 -0
- package/corpus/templates/forms/app/i18n/de-DE.ts +1 -0
- package/corpus/templates/forms/app/i18n/en-US.ts +1 -0
- package/corpus/templates/forms/app/i18n/es-ES.ts +1 -0
- package/corpus/templates/forms/app/i18n/fr-FR.ts +1 -0
- package/corpus/templates/forms/app/i18n/hi-IN.ts +1 -0
- package/corpus/templates/forms/app/i18n/ja-JP.ts +1 -0
- package/corpus/templates/forms/app/i18n/ko-KR.ts +1 -0
- package/corpus/templates/forms/app/i18n/pt-BR.ts +1 -0
- package/corpus/templates/forms/app/i18n/zh-CN.ts +1 -0
- package/corpus/templates/forms/app/i18n/zh-TW.ts +1 -0
- package/corpus/templates/forms/app/lib/route-prewarm.ts +9 -8
- package/corpus/templates/forms/app/pages/AskPage.tsx +70 -0
- package/corpus/templates/forms/app/pages/FormsListPage.tsx +74 -81
- package/corpus/templates/forms/app/root.tsx +1 -1
- package/corpus/templates/forms/app/routes/_app.ask.tsx +14 -0
- package/corpus/templates/forms/app/routes/_app.settings.tsx +54 -54
- package/corpus/templates/forms/app/routes/_app.team.tsx +2 -9
- package/corpus/templates/forms/app/routes/_index.tsx +21 -130
- package/corpus/templates/forms/changelog/2026-06-26-ask-forms-opens-as-a-standard-app-tab-with-a-simpler-sidebar.md +6 -0
- package/corpus/templates/forms/changelog/2026-06-26-forms-are-shown-in-a-tighter-row-list-with-a-denser-sidebar.md +6 -0
- package/corpus/templates/forms/shared/navigation.ts +4 -2
- package/corpus/templates/macros/app/routes/settings.tsx +54 -54
- package/corpus/templates/macros/app/routes/team.tsx +2 -10
- package/corpus/templates/mail/actions/helpers.ts +2 -2
- package/corpus/templates/mail/app/components/GoogleConnectBanner.tsx +2 -1
- package/corpus/templates/mail/app/pages/SettingsPage.tsx +5 -5
- package/corpus/templates/mail/app/routes/team.tsx +3 -2
- package/corpus/templates/mail/server/handlers/emails.ts +3 -2
- package/corpus/templates/mail/server/handlers/google-auth.ts +19 -12
- package/corpus/templates/mail/server/lib/automation-engine.ts +3 -2
- package/corpus/templates/mail/server/lib/email-state.ts +2 -3
- package/corpus/templates/mail/server/lib/google-auth.ts +28 -11
- package/corpus/templates/mail/server/lib/jobs.ts +3 -2
- package/corpus/templates/mail/server/onboarding.ts +9 -6
- package/corpus/templates/mail/server/routes/api/attachments.get.ts +3 -3
- package/corpus/templates/plan/actions/request-plan-access.ts +1 -1
- package/corpus/templates/plan/app/components/layout/Header.tsx +0 -1
- package/corpus/templates/plan/app/components/plan/CanvasArea.tsx +56 -4
- package/corpus/templates/plan/app/global.css +8 -3
- package/corpus/templates/plan/app/hooks/use-navigation-state.ts +4 -2
- package/corpus/templates/plan/app/lib/route-prewarm.ts +0 -4
- package/corpus/templates/plan/app/pages/PlansPage.tsx +1 -1
- package/corpus/templates/plan/app/routes/settings.tsx +75 -73
- package/corpus/templates/plan/app/routes/team.tsx +2 -8
- package/corpus/templates/plan/changelog/2026-06-26-canvas-grid-panning-now-stays-smooth-and-fills-the-workspace.md +6 -0
- package/corpus/templates/plan/server/lib/comment-notifications.ts +1 -1
- package/corpus/templates/slides/actions/check-image-gen.ts +2 -1
- package/corpus/templates/slides/actions/db-connect.ts +7 -45
- package/corpus/templates/slides/actions/edit-image.ts +6 -3
- package/corpus/templates/slides/actions/generate-image-api.ts +1 -1
- package/corpus/templates/slides/actions/generate-image.ts +2 -2
- package/corpus/templates/slides/actions/generate-slides-ai.ts +5 -3
- package/corpus/templates/slides/actions/image-gen-status.ts +4 -3
- package/corpus/templates/slides/actions/image-search.ts +6 -3
- package/corpus/templates/slides/actions/search-images.ts +6 -3
- package/corpus/templates/slides/app/components/CloudUpgrade.tsx +8 -51
- package/corpus/templates/slides/app/components/layout/Header.tsx +0 -1
- package/corpus/templates/slides/app/components/layout/Sidebar.tsx +0 -2
- package/corpus/templates/slides/app/routes/settings.tsx +54 -54
- package/corpus/templates/slides/app/routes/team.tsx +2 -12
- package/corpus/templates/slides/server/handlers/google-docs-auth.ts +9 -9
- package/corpus/templates/slides/server/handlers/image-gen.ts +5 -1
- package/corpus/templates/slides/server/handlers/image-providers/gemini.ts +9 -1
- package/corpus/templates/slides/server/handlers/image-providers/index.ts +18 -8
- package/corpus/templates/slides/server/handlers/image-providers/openai.ts +10 -4
- package/corpus/templates/slides/server/handlers/image-providers/types.ts +1 -0
- package/corpus/templates/slides/server/lib/google-docs-oauth.ts +59 -34
- package/corpus/templates/slides/server/register-secrets.ts +60 -0
- package/corpus/templates/videos/actions/db-connect.ts +7 -45
- package/corpus/templates/videos/app/components/CloudUpgrade.tsx +8 -51
- package/corpus/templates/videos/app/components/Sidebar.tsx +1 -9
- package/corpus/templates/videos/app/components/layout/Header.tsx +0 -1
- package/corpus/templates/videos/app/components/layout/NavSidebar.tsx +0 -3
- package/corpus/templates/videos/app/routes/settings.tsx +54 -54
- package/corpus/templates/videos/app/routes/team.tsx +2 -8
- package/dist/agent/engine/builder-engine.d.ts.map +1 -1
- package/dist/agent/engine/builder-engine.js +8 -3
- package/dist/agent/engine/builder-engine.js.map +1 -1
- package/dist/cli/mcp.d.ts.map +1 -1
- package/dist/cli/mcp.js +3 -4
- package/dist/cli/mcp.js.map +1 -1
- package/dist/client/AssistantChat.d.ts.map +1 -1
- package/dist/client/AssistantChat.js +6 -2
- package/dist/client/AssistantChat.js.map +1 -1
- package/dist/client/chat/markdown-renderer.d.ts.map +1 -1
- package/dist/client/chat/markdown-renderer.js +1 -0
- package/dist/client/chat/markdown-renderer.js.map +1 -1
- package/dist/client/i18n.d.ts.map +1 -1
- package/dist/client/i18n.js +20 -9
- package/dist/client/i18n.js.map +1 -1
- package/dist/client/index.d.ts +1 -1
- package/dist/client/index.d.ts.map +1 -1
- package/dist/client/index.js +1 -1
- package/dist/client/index.js.map +1 -1
- package/dist/client/org/OrgSwitcher.d.ts +3 -3
- package/dist/client/org/OrgSwitcher.js +2 -2
- package/dist/client/org/OrgSwitcher.js.map +1 -1
- package/dist/client/org/TeamPage.d.ts +6 -1
- package/dist/client/org/TeamPage.d.ts.map +1 -1
- package/dist/client/org/TeamPage.js +2 -2
- package/dist/client/org/TeamPage.js.map +1 -1
- package/dist/client/settings/SettingsTabsPage.d.ts +27 -0
- package/dist/client/settings/SettingsTabsPage.d.ts.map +1 -0
- package/dist/client/settings/SettingsTabsPage.js +108 -0
- package/dist/client/settings/SettingsTabsPage.js.map +1 -0
- package/dist/client/settings/index.d.ts +1 -0
- package/dist/client/settings/index.d.ts.map +1 -1
- package/dist/client/settings/index.js +1 -0
- package/dist/client/settings/index.js.map +1 -1
- package/dist/file-upload/index.d.ts +1 -1
- package/dist/file-upload/index.d.ts.map +1 -1
- package/dist/file-upload/index.js +1 -1
- package/dist/file-upload/index.js.map +1 -1
- package/dist/file-upload/registry.d.ts +1 -0
- package/dist/file-upload/registry.d.ts.map +1 -1
- package/dist/file-upload/registry.js +24 -6
- package/dist/file-upload/registry.js.map +1 -1
- package/dist/file-upload/types.d.ts +6 -1
- package/dist/file-upload/types.d.ts.map +1 -1
- package/dist/file-upload/types.js.map +1 -1
- package/dist/integrations/adapters/email.d.ts.map +1 -1
- package/dist/integrations/adapters/email.js +18 -18
- package/dist/integrations/adapters/email.js.map +1 -1
- package/dist/integrations/adapters/slack.d.ts.map +1 -1
- package/dist/integrations/adapters/slack.js +8 -7
- package/dist/integrations/adapters/slack.js.map +1 -1
- package/dist/integrations/adapters/telegram.d.ts.map +1 -1
- package/dist/integrations/adapters/telegram.js +9 -9
- package/dist/integrations/adapters/telegram.js.map +1 -1
- package/dist/integrations/adapters/whatsapp.d.ts.map +1 -1
- package/dist/integrations/adapters/whatsapp.js +10 -9
- package/dist/integrations/adapters/whatsapp.js.map +1 -1
- package/dist/integrations/plugin.d.ts.map +1 -1
- package/dist/integrations/plugin.js +47 -13
- package/dist/integrations/plugin.js.map +1 -1
- package/dist/notifications/routes.d.ts +3 -3
- package/dist/observability/routes.d.ts +6 -6
- package/dist/onboarding/default-steps.d.ts.map +1 -1
- package/dist/onboarding/default-steps.js +6 -5
- package/dist/onboarding/default-steps.js.map +1 -1
- package/dist/onboarding/types.d.ts +1 -1
- package/dist/onboarding/types.d.ts.map +1 -1
- package/dist/onboarding/types.js.map +1 -1
- package/dist/org/handlers.js +1 -1
- package/dist/org/handlers.js.map +1 -1
- package/dist/server/agent-chat-plugin.d.ts.map +1 -1
- package/dist/server/agent-chat-plugin.js +4 -6
- package/dist/server/agent-chat-plugin.js.map +1 -1
- package/dist/server/agent-engine-api-key-route.d.ts +2 -2
- package/dist/server/better-auth-instance.d.ts.map +1 -1
- package/dist/server/better-auth-instance.js +17 -56
- package/dist/server/better-auth-instance.js.map +1 -1
- package/dist/server/core-routes-plugin.d.ts +1 -1
- package/dist/server/core-routes-plugin.d.ts.map +1 -1
- package/dist/server/core-routes-plugin.js +67 -153
- package/dist/server/core-routes-plugin.js.map +1 -1
- package/dist/server/create-server.d.ts +3 -9
- package/dist/server/create-server.d.ts.map +1 -1
- package/dist/server/create-server.js +37 -91
- package/dist/server/create-server.js.map +1 -1
- package/dist/server/email-actions.d.ts +2 -3
- package/dist/server/email-actions.d.ts.map +1 -1
- package/dist/server/email-actions.js +3 -6
- package/dist/server/email-actions.js.map +1 -1
- package/dist/server/email.d.ts +3 -3
- package/dist/server/email.d.ts.map +1 -1
- package/dist/server/email.js +40 -19
- package/dist/server/email.js.map +1 -1
- package/dist/server/index.d.ts +3 -3
- package/dist/server/index.d.ts.map +1 -1
- package/dist/server/index.js +3 -3
- package/dist/server/index.js.map +1 -1
- package/dist/server/scoped-key-storage.d.ts +22 -0
- package/dist/server/scoped-key-storage.d.ts.map +1 -0
- package/dist/server/scoped-key-storage.js +152 -0
- package/dist/server/scoped-key-storage.js.map +1 -0
- package/dist/shared/agent-env.d.ts +3 -3
- package/dist/shared/agent-env.d.ts.map +1 -1
- package/dist/shared/agent-env.js +3 -3
- package/dist/shared/agent-env.js.map +1 -1
- package/dist/sharing/actions/share-resource.js +1 -1
- package/dist/sharing/actions/share-resource.js.map +1 -1
- package/dist/styles/agent-native.css +47 -3
- package/dist/templates/workspace-root/AGENTS.md +3 -2
- package/dist/templates/workspace-root/README.md +1 -1
- package/dist/templates/workspace-root/scripts/repair-workspace-org.ts +29 -90
- package/dist/terminal/pty-server.d.ts.map +1 -1
- package/dist/terminal/pty-server.js +3 -36
- package/dist/terminal/pty-server.js.map +1 -1
- package/dist/triggers/dispatcher.js +1 -1
- package/dist/triggers/dispatcher.js.map +1 -1
- package/docs/content/file-uploads.md +11 -4
- package/docs/content/locales/ar-SA/multi-app-workspace.md +3 -3
- package/docs/content/locales/de-DE/multi-app-workspace.md +3 -3
- package/docs/content/locales/es-ES/multi-app-workspace.md +3 -3
- package/docs/content/locales/fr-FR/multi-app-workspace.md +3 -3
- package/docs/content/locales/hi-IN/multi-app-workspace.md +3 -3
- package/docs/content/locales/ja-JP/multi-app-workspace.md +3 -3
- package/docs/content/locales/ko-KR/multi-app-workspace.md +3 -3
- package/docs/content/locales/pt-BR/multi-app-workspace.md +3 -3
- package/docs/content/locales/zh-CN/multi-app-workspace.md +3 -3
- package/docs/content/locales/zh-TW/multi-app-workspace.md +3 -3
- package/docs/content/multi-app-workspace.md +3 -3
- package/docs/content/template-clips.md +14 -5
- package/package.json +1 -1
- package/src/templates/workspace-root/AGENTS.md +3 -2
- package/src/templates/workspace-root/README.md +1 -1
- package/src/templates/workspace-root/scripts/repair-workspace-org.ts +29 -90
- package/corpus/core/src/server/env-var-writes.ts +0 -16
- package/corpus/templates/analytics/app/pages/Team.tsx +0 -9
- package/corpus/templates/calendar/app/pages/Team.tsx +0 -12
- package/corpus/templates/mail/app/pages/Team.tsx +0 -17
- package/dist/server/env-var-writes.d.ts +0 -10
- package/dist/server/env-var-writes.d.ts.map +0 -1
- package/dist/server/env-var-writes.js +0 -18
- package/dist/server/env-var-writes.js.map +0 -1
|
@@ -24,6 +24,7 @@ import {
|
|
|
24
24
|
IconClipboardCopy,
|
|
25
25
|
IconFileText,
|
|
26
26
|
IconSparkles,
|
|
27
|
+
IconLayoutSidebarRightExpand,
|
|
27
28
|
} from "@tabler/icons-react";
|
|
28
29
|
import { useQuery } from "@tanstack/react-query";
|
|
29
30
|
import { useCallback, useEffect, useRef, useState } from "react";
|
|
@@ -33,7 +34,7 @@ import { toast } from "sonner";
|
|
|
33
34
|
import { EditableRecordingTitle } from "@/components/editable-recording-title";
|
|
34
35
|
import { EditorLayout } from "@/components/editor/editor-layout";
|
|
35
36
|
import { CommentsPanel } from "@/components/player/comments-panel";
|
|
36
|
-
import {
|
|
37
|
+
import { RecordingOptionsMenu } from "@/components/player/delete-recording-menu";
|
|
37
38
|
import { InsightsPanel } from "@/components/player/insights-panel";
|
|
38
39
|
import { ReactionsTray } from "@/components/player/reactions-tray";
|
|
39
40
|
import { SettingsPanel } from "@/components/player/settings-panel";
|
|
@@ -54,6 +55,12 @@ import {
|
|
|
54
55
|
DropdownMenuSeparator,
|
|
55
56
|
DropdownMenuTrigger,
|
|
56
57
|
} from "@/components/ui/dropdown-menu";
|
|
58
|
+
import {
|
|
59
|
+
Sheet,
|
|
60
|
+
SheetContent,
|
|
61
|
+
SheetDescription,
|
|
62
|
+
SheetTitle,
|
|
63
|
+
} from "@/components/ui/sheet";
|
|
57
64
|
import { Spinner } from "@/components/ui/spinner";
|
|
58
65
|
import { Tabs, TabsList, TabsTrigger, TabsContent } from "@/components/ui/tabs";
|
|
59
66
|
import {
|
|
@@ -100,6 +107,20 @@ interface GeneratedWorkflowState {
|
|
|
100
107
|
error?: string;
|
|
101
108
|
}
|
|
102
109
|
|
|
110
|
+
function useIsCompactRecordingLayout() {
|
|
111
|
+
const [isCompact, setIsCompact] = useState(false);
|
|
112
|
+
|
|
113
|
+
useEffect(() => {
|
|
114
|
+
const query = window.matchMedia("(max-width: 1279px)");
|
|
115
|
+
const update = () => setIsCompact(query.matches);
|
|
116
|
+
update();
|
|
117
|
+
query.addEventListener("change", update);
|
|
118
|
+
return () => query.removeEventListener("change", update);
|
|
119
|
+
}, []);
|
|
120
|
+
|
|
121
|
+
return isCompact;
|
|
122
|
+
}
|
|
123
|
+
|
|
103
124
|
function isNativeSaveFailureReason(reason: string | null | undefined): boolean {
|
|
104
125
|
return /native recording upload|native fullscreen|screencapture|avconvert/i.test(
|
|
105
126
|
reason ?? "",
|
|
@@ -129,6 +150,7 @@ function nativeSaveFailureMessage(reason: string | null | undefined): string {
|
|
|
129
150
|
|
|
130
151
|
function InsightsUnavailableState() {
|
|
131
152
|
const t = useT();
|
|
153
|
+
|
|
132
154
|
return (
|
|
133
155
|
<div className="flex h-full flex-col items-center justify-center px-8 py-12 text-center">
|
|
134
156
|
<p className="text-sm font-medium text-foreground">
|
|
@@ -179,15 +201,18 @@ export default function RecordingPage() {
|
|
|
179
201
|
const playerRef = useRef<VideoPlayerHandle | null>(null);
|
|
180
202
|
|
|
181
203
|
const [panel, setPanel] = useState<SidePanel>("agent");
|
|
204
|
+
const [sidePanelOpen, setSidePanelOpen] = useState(false);
|
|
182
205
|
const [theaterMode, setTheaterMode] = useState(false);
|
|
183
206
|
const [editing, setEditing] = useState(false);
|
|
184
207
|
const [currentMs, setCurrentMs] = useState(0);
|
|
208
|
+
const isCompactLayout = useIsCompactRecordingLayout();
|
|
185
209
|
const transcriptKickedRef = useRef<string | null>(null);
|
|
186
210
|
// When the recording lands in the processing state but never flips to
|
|
187
211
|
// 'ready', stop spinning forever and surface an error banner so the user
|
|
188
212
|
// can retry or report the issue instead of staring at a spinner.
|
|
189
213
|
const [processingTimeout, setProcessingTimeout] = useState(false);
|
|
190
214
|
const [retryingFinalize, setRetryingFinalize] = useState(false);
|
|
215
|
+
const [downloading, setDownloading] = useState(false);
|
|
191
216
|
|
|
192
217
|
useEffect(() => {
|
|
193
218
|
if (
|
|
@@ -282,6 +307,30 @@ export default function RecordingPage() {
|
|
|
282
307
|
const isLoomRecording = isLoomRecordingSource(recording);
|
|
283
308
|
const canUseNativeEditor = canEdit && !isLoomEmbedBacked;
|
|
284
309
|
const canDelete = role === "owner";
|
|
310
|
+
const canDownloadRecording = Boolean(
|
|
311
|
+
recording?.enableDownloads && recording.videoUrl && !isLoomEmbedBacked,
|
|
312
|
+
);
|
|
313
|
+
const downloadRecording = useCallback(async () => {
|
|
314
|
+
if (!recording?.videoUrl) return;
|
|
315
|
+
setDownloading(true);
|
|
316
|
+
try {
|
|
317
|
+
const res = await fetch(recording.videoUrl);
|
|
318
|
+
if (!res.ok) throw new Error(`HTTP ${res.status}`);
|
|
319
|
+
const blob = await res.blob();
|
|
320
|
+
const url = URL.createObjectURL(blob);
|
|
321
|
+
const a = document.createElement("a");
|
|
322
|
+
a.href = url;
|
|
323
|
+
a.download = `${sanitizeFilename(recording.title || "clip")}.mp4`;
|
|
324
|
+
document.body.appendChild(a);
|
|
325
|
+
a.click();
|
|
326
|
+
a.remove();
|
|
327
|
+
URL.revokeObjectURL(url);
|
|
328
|
+
} catch {
|
|
329
|
+
window.open(recording.videoUrl, "_blank", "noopener,noreferrer");
|
|
330
|
+
} finally {
|
|
331
|
+
setDownloading(false);
|
|
332
|
+
}
|
|
333
|
+
}, [recording?.title, recording?.videoUrl]);
|
|
285
334
|
const retryFinalizeAfterStorage = useCallback(async () => {
|
|
286
335
|
if (!recordingId) return;
|
|
287
336
|
setRetryingFinalize(true);
|
|
@@ -413,6 +462,10 @@ export default function RecordingPage() {
|
|
|
413
462
|
if (!canUseNativeEditor && editing) setEditing(false);
|
|
414
463
|
}, [canUseNativeEditor, editing]);
|
|
415
464
|
|
|
465
|
+
useEffect(() => {
|
|
466
|
+
if (editing || !isCompactLayout) setSidePanelOpen(false);
|
|
467
|
+
}, [editing, isCompactLayout]);
|
|
468
|
+
|
|
416
469
|
useEffect(() => {
|
|
417
470
|
if (!recording) return;
|
|
418
471
|
document.title = isDefaultTitle(recording.title)
|
|
@@ -647,6 +700,158 @@ export default function RecordingPage() {
|
|
|
647
700
|
);
|
|
648
701
|
}
|
|
649
702
|
|
|
703
|
+
const renderSidePanel = (compact = false) => (
|
|
704
|
+
<Tabs
|
|
705
|
+
value={panel}
|
|
706
|
+
onValueChange={(v) => setPanel(v as SidePanel)}
|
|
707
|
+
className={cn("flex h-full flex-col", compact && "pt-8")}
|
|
708
|
+
>
|
|
709
|
+
<TabsList
|
|
710
|
+
className={cn(
|
|
711
|
+
"mx-3 mt-3 grid w-auto",
|
|
712
|
+
canEdit ? "grid-cols-5" : "grid-cols-4",
|
|
713
|
+
)}
|
|
714
|
+
>
|
|
715
|
+
<TabsTrigger value="agent" className="min-w-0 px-2 text-xs">
|
|
716
|
+
{t("recordingPage.agent")}
|
|
717
|
+
</TabsTrigger>
|
|
718
|
+
<TabsTrigger value="comments" className="min-w-0 px-2 text-xs">
|
|
719
|
+
{t("recordingPage.activity")}
|
|
720
|
+
</TabsTrigger>
|
|
721
|
+
<TabsTrigger value="transcript" className="min-w-0 px-2 text-xs">
|
|
722
|
+
{t("recordingPage.transcript")}
|
|
723
|
+
</TabsTrigger>
|
|
724
|
+
<TabsTrigger value="insights" className="min-w-0 px-2 text-xs">
|
|
725
|
+
{t("recordingPage.insights")}
|
|
726
|
+
</TabsTrigger>
|
|
727
|
+
{canEdit ? (
|
|
728
|
+
<TabsTrigger value="settings" className="min-w-0 px-2 text-xs">
|
|
729
|
+
{t("recordingPage.settings")}
|
|
730
|
+
</TabsTrigger>
|
|
731
|
+
) : null}
|
|
732
|
+
</TabsList>
|
|
733
|
+
|
|
734
|
+
<TabsContent
|
|
735
|
+
value="agent"
|
|
736
|
+
className="mt-0 flex flex-1 min-h-0 flex-col data-[state=inactive]:hidden"
|
|
737
|
+
>
|
|
738
|
+
<AgentPanel
|
|
739
|
+
browserTabId={getBrowserTabId()}
|
|
740
|
+
emptyStateText={t("recordingPage.askAboutClip")}
|
|
741
|
+
dynamicSuggestions={false}
|
|
742
|
+
chatNotice={
|
|
743
|
+
generatedWorkflow ? (
|
|
744
|
+
<GeneratedWorkflowNotice workflow={generatedWorkflow} />
|
|
745
|
+
) : null
|
|
746
|
+
}
|
|
747
|
+
suggestions={
|
|
748
|
+
canEdit
|
|
749
|
+
? [
|
|
750
|
+
t("recordingPage.summarizeClip"),
|
|
751
|
+
t("recordingPage.generateChapters"),
|
|
752
|
+
t("recordingPage.findActionItems"),
|
|
753
|
+
t("recordingPage.draftRecap"),
|
|
754
|
+
]
|
|
755
|
+
: [
|
|
756
|
+
t("recordingPage.summarizeClip"),
|
|
757
|
+
t("recordingPage.findKeyMoments"),
|
|
758
|
+
t("recordingPage.listFollowUpActions"),
|
|
759
|
+
t("recordingPage.draftQuestions"),
|
|
760
|
+
]
|
|
761
|
+
}
|
|
762
|
+
/>
|
|
763
|
+
</TabsContent>
|
|
764
|
+
<TabsContent
|
|
765
|
+
value="transcript"
|
|
766
|
+
className="flex-1 min-h-0 mt-3 data-[state=inactive]:hidden"
|
|
767
|
+
>
|
|
768
|
+
<TranscriptPanel
|
|
769
|
+
segments={transcriptSegments}
|
|
770
|
+
fullText={transcriptFullText}
|
|
771
|
+
durationMs={recording.durationMs}
|
|
772
|
+
currentMs={currentMs}
|
|
773
|
+
onSeek={(ms) => playerRef.current?.seek(ms)}
|
|
774
|
+
status={transcriptStatus}
|
|
775
|
+
failureReason={transcriptFailureReason}
|
|
776
|
+
cleanup={transcriptCleanup}
|
|
777
|
+
recordingTitle={recording.title}
|
|
778
|
+
onRetry={() => {
|
|
779
|
+
// Force a fresh transcript job, then let polling swap the panel
|
|
780
|
+
// back to the pending state while it runs.
|
|
781
|
+
fetch(
|
|
782
|
+
agentNativePath("/_agent-native/actions/request-transcript"),
|
|
783
|
+
{
|
|
784
|
+
method: "POST",
|
|
785
|
+
headers: { "Content-Type": "application/json" },
|
|
786
|
+
body: JSON.stringify({
|
|
787
|
+
recordingId: recording.id,
|
|
788
|
+
force: true,
|
|
789
|
+
}),
|
|
790
|
+
},
|
|
791
|
+
)
|
|
792
|
+
.then((res) => {
|
|
793
|
+
if (!res.ok) throw new Error(`HTTP ${res.status}`);
|
|
794
|
+
})
|
|
795
|
+
.catch((err) =>
|
|
796
|
+
toast.error(
|
|
797
|
+
t("recordingPage.retryFailed", {
|
|
798
|
+
message: err?.message ?? t("recordingPage.networkError"),
|
|
799
|
+
}),
|
|
800
|
+
),
|
|
801
|
+
)
|
|
802
|
+
.finally(() => playerDataQ.refetch());
|
|
803
|
+
}}
|
|
804
|
+
/>
|
|
805
|
+
</TabsContent>
|
|
806
|
+
<TabsContent
|
|
807
|
+
value="comments"
|
|
808
|
+
className="flex-1 min-h-0 mt-3 data-[state=inactive]:hidden"
|
|
809
|
+
>
|
|
810
|
+
<CommentsPanel
|
|
811
|
+
recordingId={recording.id}
|
|
812
|
+
comments={comments}
|
|
813
|
+
currentMs={currentMs}
|
|
814
|
+
currentUserEmail={session?.email}
|
|
815
|
+
enableComments={recording.enableComments}
|
|
816
|
+
onSeek={(ms) => playerRef.current?.seek(ms)}
|
|
817
|
+
queryKey={[
|
|
818
|
+
"action",
|
|
819
|
+
"get-recording-player-data",
|
|
820
|
+
{ recordingId: recordingId ?? "" },
|
|
821
|
+
]}
|
|
822
|
+
/>
|
|
823
|
+
</TabsContent>
|
|
824
|
+
<TabsContent
|
|
825
|
+
value="insights"
|
|
826
|
+
className="flex-1 min-h-0 mt-3 overflow-y-auto data-[state=inactive]:hidden"
|
|
827
|
+
>
|
|
828
|
+
{canEdit ? (
|
|
829
|
+
<InsightsPanel
|
|
830
|
+
recordingId={recording.id}
|
|
831
|
+
durationMs={recording.durationMs}
|
|
832
|
+
/>
|
|
833
|
+
) : (
|
|
834
|
+
<InsightsUnavailableState />
|
|
835
|
+
)}
|
|
836
|
+
</TabsContent>
|
|
837
|
+
{canEdit ? (
|
|
838
|
+
<TabsContent
|
|
839
|
+
value="settings"
|
|
840
|
+
className="mt-3 flex flex-1 min-h-0 flex-col data-[state=inactive]:hidden"
|
|
841
|
+
>
|
|
842
|
+
<SettingsPanel
|
|
843
|
+
recording={recording}
|
|
844
|
+
visibility={recording.visibility}
|
|
845
|
+
ctas={ctas}
|
|
846
|
+
onClose={() => setPanel("agent")}
|
|
847
|
+
onRefetch={() => playerDataQ.refetch()}
|
|
848
|
+
showHeader={false}
|
|
849
|
+
/>
|
|
850
|
+
</TabsContent>
|
|
851
|
+
) : null}
|
|
852
|
+
</Tabs>
|
|
853
|
+
);
|
|
854
|
+
|
|
650
855
|
return (
|
|
651
856
|
<div className="flex h-screen w-full bg-background overflow-hidden">
|
|
652
857
|
{/* Main video column */}
|
|
@@ -797,6 +1002,23 @@ export default function RecordingPage() {
|
|
|
797
1002
|
</DropdownMenu>
|
|
798
1003
|
) : null}
|
|
799
1004
|
|
|
1005
|
+
{!editing ? (
|
|
1006
|
+
<Tooltip>
|
|
1007
|
+
<TooltipTrigger asChild>
|
|
1008
|
+
<Button
|
|
1009
|
+
variant="outline"
|
|
1010
|
+
size="icon"
|
|
1011
|
+
className="xl:hidden"
|
|
1012
|
+
onClick={() => setSidePanelOpen(true)}
|
|
1013
|
+
aria-label={t("recordingPage.details")}
|
|
1014
|
+
>
|
|
1015
|
+
<IconLayoutSidebarRightExpand className="h-4 w-4" />
|
|
1016
|
+
</Button>
|
|
1017
|
+
</TooltipTrigger>
|
|
1018
|
+
<TooltipContent>{t("recordingPage.details")}</TooltipContent>
|
|
1019
|
+
</Tooltip>
|
|
1020
|
+
) : null}
|
|
1021
|
+
|
|
800
1022
|
<ShareRecordingPopover
|
|
801
1023
|
recordingId={recording.id}
|
|
802
1024
|
recordingTitle={recording.title}
|
|
@@ -814,9 +1036,15 @@ export default function RecordingPage() {
|
|
|
814
1036
|
</Button>
|
|
815
1037
|
</ShareRecordingPopover>
|
|
816
1038
|
|
|
817
|
-
{canDelete ? (
|
|
818
|
-
<
|
|
1039
|
+
{canDelete || canDownloadRecording ? (
|
|
1040
|
+
<RecordingOptionsMenu
|
|
819
1041
|
recordingId={recording.id}
|
|
1042
|
+
canDelete={canDelete}
|
|
1043
|
+
canDownload={canDownloadRecording}
|
|
1044
|
+
downloadPending={downloading}
|
|
1045
|
+
onDownload={() => {
|
|
1046
|
+
void downloadRecording();
|
|
1047
|
+
}}
|
|
820
1048
|
onDeleted={() => navigate("/library", { replace: true })}
|
|
821
1049
|
/>
|
|
822
1050
|
) : null}
|
|
@@ -935,162 +1163,29 @@ export default function RecordingPage() {
|
|
|
935
1163
|
|
|
936
1164
|
{/* Side panel */}
|
|
937
1165
|
{!editing ? (
|
|
938
|
-
|
|
939
|
-
|
|
940
|
-
|
|
941
|
-
|
|
942
|
-
|
|
943
|
-
|
|
944
|
-
<TabsList
|
|
945
|
-
className={cn(
|
|
946
|
-
"mx-3 mt-3 grid w-auto",
|
|
947
|
-
canEdit ? "grid-cols-5" : "grid-cols-4",
|
|
948
|
-
)}
|
|
949
|
-
>
|
|
950
|
-
<TabsTrigger value="agent" className="min-w-0 px-2 text-xs">
|
|
951
|
-
{t("recordingPage.agent")}
|
|
952
|
-
</TabsTrigger>
|
|
953
|
-
<TabsTrigger value="comments" className="min-w-0 px-2 text-xs">
|
|
954
|
-
{t("recordingPage.activity")}
|
|
955
|
-
</TabsTrigger>
|
|
956
|
-
<TabsTrigger value="transcript" className="min-w-0 px-2 text-xs">
|
|
957
|
-
{t("recordingPage.transcript")}
|
|
958
|
-
</TabsTrigger>
|
|
959
|
-
<TabsTrigger value="insights" className="min-w-0 px-2 text-xs">
|
|
960
|
-
{t("recordingPage.insights")}
|
|
961
|
-
</TabsTrigger>
|
|
962
|
-
{canEdit ? (
|
|
963
|
-
<TabsTrigger value="settings" className="min-w-0 px-2 text-xs">
|
|
964
|
-
{t("recordingPage.settings")}
|
|
965
|
-
</TabsTrigger>
|
|
966
|
-
) : null}
|
|
967
|
-
</TabsList>
|
|
968
|
-
|
|
969
|
-
<TabsContent
|
|
970
|
-
value="agent"
|
|
971
|
-
className="mt-0 flex flex-1 min-h-0 flex-col data-[state=inactive]:hidden"
|
|
972
|
-
>
|
|
973
|
-
<AgentPanel
|
|
974
|
-
browserTabId={getBrowserTabId()}
|
|
975
|
-
emptyStateText={t("recordingPage.askAboutClip")}
|
|
976
|
-
dynamicSuggestions={false}
|
|
977
|
-
chatNotice={
|
|
978
|
-
generatedWorkflow ? (
|
|
979
|
-
<GeneratedWorkflowNotice workflow={generatedWorkflow} />
|
|
980
|
-
) : null
|
|
981
|
-
}
|
|
982
|
-
suggestions={
|
|
983
|
-
canEdit
|
|
984
|
-
? [
|
|
985
|
-
t("recordingPage.summarizeClip"),
|
|
986
|
-
t("recordingPage.generateChapters"),
|
|
987
|
-
t("recordingPage.findActionItems"),
|
|
988
|
-
t("recordingPage.draftRecap"),
|
|
989
|
-
]
|
|
990
|
-
: [
|
|
991
|
-
t("recordingPage.summarizeClip"),
|
|
992
|
-
t("recordingPage.findKeyMoments"),
|
|
993
|
-
t("recordingPage.listFollowUpActions"),
|
|
994
|
-
t("recordingPage.draftQuestions"),
|
|
995
|
-
]
|
|
996
|
-
}
|
|
997
|
-
/>
|
|
998
|
-
</TabsContent>
|
|
999
|
-
<TabsContent
|
|
1000
|
-
value="transcript"
|
|
1001
|
-
className="flex-1 min-h-0 mt-3 data-[state=inactive]:hidden"
|
|
1002
|
-
>
|
|
1003
|
-
<TranscriptPanel
|
|
1004
|
-
segments={transcriptSegments}
|
|
1005
|
-
fullText={transcriptFullText}
|
|
1006
|
-
durationMs={recording.durationMs}
|
|
1007
|
-
currentMs={currentMs}
|
|
1008
|
-
onSeek={(ms) => playerRef.current?.seek(ms)}
|
|
1009
|
-
status={transcriptStatus}
|
|
1010
|
-
failureReason={transcriptFailureReason}
|
|
1011
|
-
cleanup={transcriptCleanup}
|
|
1012
|
-
recordingTitle={recording.title}
|
|
1013
|
-
onRetry={() => {
|
|
1014
|
-
// Re-run transcription now that the user may have connected
|
|
1015
|
-
// Builder/Gemini or after a one-off network error. The action
|
|
1016
|
-
// flips the row to 'pending' first, so the UI swaps back to
|
|
1017
|
-
// "Transcribing…".
|
|
1018
|
-
fetch(
|
|
1019
|
-
agentNativePath(
|
|
1020
|
-
"/_agent-native/actions/request-transcript",
|
|
1021
|
-
),
|
|
1022
|
-
{
|
|
1023
|
-
method: "POST",
|
|
1024
|
-
headers: { "Content-Type": "application/json" },
|
|
1025
|
-
body: JSON.stringify({
|
|
1026
|
-
recordingId: recording.id,
|
|
1027
|
-
force: true,
|
|
1028
|
-
}),
|
|
1029
|
-
},
|
|
1030
|
-
)
|
|
1031
|
-
.then((res) => {
|
|
1032
|
-
if (!res.ok) throw new Error(`HTTP ${res.status}`);
|
|
1033
|
-
})
|
|
1034
|
-
.catch((err) =>
|
|
1035
|
-
toast.error(
|
|
1036
|
-
t("recordingPage.retryFailed", {
|
|
1037
|
-
message:
|
|
1038
|
-
err?.message ?? t("recordingPage.networkError"),
|
|
1039
|
-
}),
|
|
1040
|
-
),
|
|
1041
|
-
)
|
|
1042
|
-
.finally(() => playerDataQ.refetch());
|
|
1043
|
-
}}
|
|
1044
|
-
/>
|
|
1045
|
-
</TabsContent>
|
|
1046
|
-
<TabsContent
|
|
1047
|
-
value="comments"
|
|
1048
|
-
className="flex-1 min-h-0 mt-3 data-[state=inactive]:hidden"
|
|
1049
|
-
>
|
|
1050
|
-
<CommentsPanel
|
|
1051
|
-
recordingId={recording.id}
|
|
1052
|
-
comments={comments}
|
|
1053
|
-
currentMs={currentMs}
|
|
1054
|
-
currentUserEmail={session?.email}
|
|
1055
|
-
enableComments={recording.enableComments}
|
|
1056
|
-
onSeek={(ms) => playerRef.current?.seek(ms)}
|
|
1057
|
-
queryKey={[
|
|
1058
|
-
"action",
|
|
1059
|
-
"get-recording-player-data",
|
|
1060
|
-
{ recordingId: recordingId ?? "" },
|
|
1061
|
-
]}
|
|
1062
|
-
/>
|
|
1063
|
-
</TabsContent>
|
|
1064
|
-
<TabsContent
|
|
1065
|
-
value="insights"
|
|
1066
|
-
className="flex-1 min-h-0 mt-3 overflow-y-auto data-[state=inactive]:hidden"
|
|
1067
|
-
>
|
|
1068
|
-
{canEdit ? (
|
|
1069
|
-
<InsightsPanel
|
|
1070
|
-
recordingId={recording.id}
|
|
1071
|
-
durationMs={recording.durationMs}
|
|
1072
|
-
/>
|
|
1073
|
-
) : (
|
|
1074
|
-
<InsightsUnavailableState />
|
|
1075
|
-
)}
|
|
1076
|
-
</TabsContent>
|
|
1077
|
-
{canEdit ? (
|
|
1078
|
-
<TabsContent
|
|
1079
|
-
value="settings"
|
|
1080
|
-
className="mt-3 flex flex-1 min-h-0 flex-col data-[state=inactive]:hidden"
|
|
1166
|
+
<>
|
|
1167
|
+
{isCompactLayout ? (
|
|
1168
|
+
<Sheet open={sidePanelOpen} onOpenChange={setSidePanelOpen}>
|
|
1169
|
+
<SheetContent
|
|
1170
|
+
side="right"
|
|
1171
|
+
className="flex h-full w-[calc(100vw-24px)] max-w-[420px] flex-col gap-0 p-0 sm:max-w-[420px]"
|
|
1081
1172
|
>
|
|
1082
|
-
<
|
|
1083
|
-
|
|
1084
|
-
|
|
1085
|
-
|
|
1086
|
-
|
|
1087
|
-
|
|
1088
|
-
|
|
1089
|
-
|
|
1090
|
-
|
|
1091
|
-
|
|
1092
|
-
|
|
1093
|
-
|
|
1173
|
+
<SheetTitle className="sr-only">
|
|
1174
|
+
{t("recordingPage.details")}
|
|
1175
|
+
</SheetTitle>
|
|
1176
|
+
<SheetDescription className="sr-only">
|
|
1177
|
+
{t("recordingPage.askAboutClip")}
|
|
1178
|
+
</SheetDescription>
|
|
1179
|
+
{renderSidePanel(true)}
|
|
1180
|
+
</SheetContent>
|
|
1181
|
+
</Sheet>
|
|
1182
|
+
) : null}
|
|
1183
|
+
{!isCompactLayout ? (
|
|
1184
|
+
<aside className="hidden w-[380px] shrink-0 flex-col border-s border-border bg-background xl:flex">
|
|
1185
|
+
{renderSidePanel()}
|
|
1186
|
+
</aside>
|
|
1187
|
+
) : null}
|
|
1188
|
+
</>
|
|
1094
1189
|
) : null}
|
|
1095
1190
|
</div>
|
|
1096
1191
|
);
|
|
@@ -1220,6 +1315,16 @@ function displayRecordingTitle(title: string | null | undefined): string {
|
|
|
1220
1315
|
return isDefaultTitle(title) ? "Untitled Clip" : (title ?? "").trim();
|
|
1221
1316
|
}
|
|
1222
1317
|
|
|
1318
|
+
function sanitizeFilename(name: string): string {
|
|
1319
|
+
return (
|
|
1320
|
+
name
|
|
1321
|
+
.trim()
|
|
1322
|
+
.replace(/[^\w.-]+/g, "-")
|
|
1323
|
+
.replace(/^-+|-+$/g, "")
|
|
1324
|
+
.slice(0, 80) || "clip"
|
|
1325
|
+
);
|
|
1326
|
+
}
|
|
1327
|
+
|
|
1223
1328
|
function shouldShowGeneratedTitleSkeleton(
|
|
1224
1329
|
recording: { title: string | null | undefined; createdAt?: string | null },
|
|
1225
1330
|
transcriptStatus?: string,
|
|
@@ -38,7 +38,7 @@ import { useLoaderData, useNavigate, useParams } from "react-router";
|
|
|
38
38
|
import { CaptureInstallButton } from "@/components/capture-install-options";
|
|
39
39
|
import { AccessPasswordPrompt } from "@/components/player/access-password-prompt";
|
|
40
40
|
import { CommentsPanel } from "@/components/player/comments-panel";
|
|
41
|
-
import {
|
|
41
|
+
import { RecordingOptionsMenu } from "@/components/player/delete-recording-menu";
|
|
42
42
|
import { ReactionsTray } from "@/components/player/reactions-tray";
|
|
43
43
|
import { ShareRecordingPopover } from "@/components/player/share-dialog";
|
|
44
44
|
import { SignInPromptDialog } from "@/components/player/sign-in-prompt-dialog";
|
|
@@ -797,8 +797,16 @@ export default function ShareRoute() {
|
|
|
797
797
|
</DropdownMenu>
|
|
798
798
|
) : null}
|
|
799
799
|
{viewerIsOwner ? (
|
|
800
|
-
<
|
|
800
|
+
<RecordingOptionsMenu
|
|
801
801
|
recordingId={recording.id}
|
|
802
|
+
canDelete
|
|
803
|
+
canDownload={canDownloadRecording}
|
|
804
|
+
downloadPending={downloading}
|
|
805
|
+
downloadLabel={t("sharePage.downloadMp4")}
|
|
806
|
+
downloadingLabel={t("sharePage.downloading")}
|
|
807
|
+
onDownload={() => {
|
|
808
|
+
void downloadRecording();
|
|
809
|
+
}}
|
|
802
810
|
onDeleted={() => navigate("/library", { replace: true })}
|
|
803
811
|
/>
|
|
804
812
|
) : null}
|