@agent-native/core 0.100.2 → 0.101.3
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 +83 -0
- package/corpus/core/docs/content/locales/ar-SA/pr-visual-recap.mdx +48 -30
- package/corpus/core/docs/content/locales/ar-SA/template-plan.mdx +7 -0
- package/corpus/core/docs/content/locales/de-DE/pr-visual-recap.mdx +48 -30
- package/corpus/core/docs/content/locales/de-DE/template-plan.mdx +7 -0
- package/corpus/core/docs/content/locales/es-ES/pr-visual-recap.mdx +48 -30
- package/corpus/core/docs/content/locales/es-ES/template-plan.mdx +14 -0
- package/corpus/core/docs/content/locales/fr-FR/pr-visual-recap.mdx +48 -30
- package/corpus/core/docs/content/locales/fr-FR/template-plan.mdx +7 -0
- package/corpus/core/docs/content/locales/hi-IN/pr-visual-recap.mdx +48 -30
- package/corpus/core/docs/content/locales/hi-IN/template-plan.mdx +7 -0
- package/corpus/core/docs/content/locales/ja-JP/pr-visual-recap.mdx +48 -30
- package/corpus/core/docs/content/locales/ja-JP/template-plan.mdx +7 -0
- package/corpus/core/docs/content/locales/ko-KR/pr-visual-recap.mdx +48 -30
- package/corpus/core/docs/content/locales/ko-KR/template-plan.mdx +7 -0
- package/corpus/core/docs/content/locales/pt-BR/pr-visual-recap.mdx +48 -30
- package/corpus/core/docs/content/locales/pt-BR/template-plan.mdx +14 -0
- package/corpus/core/docs/content/locales/zh-CN/pr-visual-recap.mdx +48 -30
- package/corpus/core/docs/content/locales/zh-CN/template-plan.mdx +7 -0
- package/corpus/core/docs/content/locales/zh-TW/pr-visual-recap.mdx +48 -30
- package/corpus/core/docs/content/locales/zh-TW/template-plan.mdx +7 -0
- package/corpus/core/docs/content/pr-visual-recap.mdx +50 -32
- package/corpus/core/docs/content/template-plan.mdx +14 -0
- package/corpus/core/docs/content/toolkit-comments-review.mdx +16 -2
- package/corpus/core/package.json +4 -1
- package/corpus/core/src/a2a/index.ts +2 -1
- package/corpus/core/src/a2a/server.ts +34 -9
- package/corpus/core/src/agent/production-agent.ts +56 -10
- package/corpus/core/src/cli/create.ts +47 -19
- package/corpus/core/src/cli/pr-visual-recap-workflow.ts +2 -3
- package/corpus/core/src/cli/recap.ts +3 -4932
- package/corpus/core/src/cli/skills-content/visual-plan-skill.ts +6 -4
- package/corpus/core/src/cli/skills-content/visual-recap-skill.ts +7 -1
- package/corpus/core/src/client/AgentPanel.tsx +19 -17
- package/corpus/core/src/client/analytics.ts +8 -1
- package/corpus/core/src/client/chat/markdown-renderer.tsx +54 -8
- package/corpus/core/src/client/chat/message-components.tsx +8 -2
- package/corpus/core/src/client/clipboard.ts +28 -1
- package/corpus/core/src/client/guided-questions.tsx +4 -0
- package/corpus/core/src/client/i18n.tsx +2 -1
- package/corpus/core/src/client/index.ts +4 -0
- package/corpus/core/src/client/review/ReviewCommentComposer.tsx +108 -0
- package/corpus/core/src/client/review/ReviewThreadPanel.tsx +482 -150
- package/corpus/core/src/client/review/index.ts +8 -0
- package/corpus/core/src/client/review/use-review.ts +35 -1
- package/corpus/core/src/client/use-agent-chat-context.ts +3 -2
- package/corpus/core/src/credentials/index.ts +41 -8
- package/corpus/core/src/extensions/fetch-tool.ts +33 -3
- package/corpus/core/src/notifications/channels.ts +20 -6
- package/corpus/core/src/review/actions/create-review-comment.ts +2 -1
- package/corpus/core/src/review/actions/get-review-feedback.ts +6 -11
- package/corpus/core/src/review/actions/list-review-comments.ts +38 -4
- package/corpus/core/src/review/actions/reply-review-comment.ts +33 -22
- package/corpus/core/src/review/actions/resolve-review-thread.ts +29 -2
- package/corpus/core/src/review/actions/send-review-thread-to-agent.ts +62 -0
- package/corpus/core/src/review/identity.ts +101 -0
- package/corpus/core/src/review/index.ts +14 -0
- package/corpus/core/src/review/store.ts +315 -8
- package/corpus/core/src/review/types.ts +4 -0
- package/corpus/core/src/secrets/crypto.ts +26 -10
- package/corpus/core/src/secrets/storage.ts +16 -3
- package/corpus/core/src/server/action-discovery.ts +4 -0
- package/corpus/core/src/server/action-routes.ts +125 -4
- package/corpus/core/src/server/agent-chat/plugin-options.ts +16 -0
- package/corpus/core/src/server/agent-chat-plugin.ts +61 -7
- package/corpus/core/src/server/derived-secret.ts +5 -1
- package/corpus/core/src/server/index.ts +8 -0
- package/corpus/core/src/vite/action-types-plugin.ts +4 -0
- package/corpus/templates/analytics/changelog/2026-07-14-daily-dashboard-email-captures-authenticate-with-a-sessi.md +6 -0
- package/corpus/templates/analytics/changelog/2026-07-14-long-running-cross-app-analyses-now-continue-reliably-in-the.md +6 -0
- package/corpus/templates/analytics/server/lib/dashboard-report.ts +156 -3
- package/corpus/templates/analytics/server/plugins/agent-chat.ts +8 -4
- package/corpus/templates/assets/app/components/generation/GenerationResults.tsx +402 -142
- package/corpus/templates/assets/app/i18n/zh-TW.ts +1 -0
- package/corpus/templates/assets/app/i18n-data.ts +1 -0
- package/corpus/templates/assets/app/routes/library.tsx +187 -48
- package/corpus/templates/assets/changelog/2026-07-13-merged-the-candidates-panel-into-the-library-as-a-drafts-tab.md +6 -0
- package/corpus/templates/chat/app/lib/agent-page.tsx +40 -0
- package/corpus/templates/chat/app/routes/agent.tsx +5 -3
- package/corpus/templates/chat/changelog/2026-07-14-fixed-chat-template-startup-with-older-core-versions.md +6 -0
- package/corpus/templates/clips/.agents/skills/ai-video-tools/SKILL.md +5 -0
- package/corpus/templates/clips/AGENTS.md +4 -0
- package/corpus/templates/clips/actions/get-feature-flags.ts +30 -0
- package/corpus/templates/clips/actions/lib/transcript-preview.ts +48 -0
- package/corpus/templates/clips/actions/request-transcript.ts +41 -1
- package/corpus/templates/clips/actions/view-screen.ts +5 -9
- package/corpus/templates/clips/app/components/library/library-layout.tsx +1 -1
- package/corpus/templates/clips/app/components/player/share-dialog.tsx +44 -81
- package/corpus/templates/clips/app/components/player/video-player.tsx +39 -1
- package/corpus/templates/clips/app/hooks/use-desktop-promo.ts +6 -12
- package/corpus/templates/clips/app/hooks/use-mse-video-source.ts +146 -0
- package/corpus/templates/clips/app/i18n/ar-SA.ts +0 -8
- package/corpus/templates/clips/app/i18n/de-DE.ts +0 -9
- package/corpus/templates/clips/app/i18n/en-US.ts +0 -8
- package/corpus/templates/clips/app/i18n/es-ES.ts +0 -9
- package/corpus/templates/clips/app/i18n/fr-FR.ts +0 -9
- package/corpus/templates/clips/app/i18n/hi-IN.ts +0 -8
- package/corpus/templates/clips/app/i18n/ja-JP.ts +0 -9
- package/corpus/templates/clips/app/i18n/ko-KR.ts +0 -9
- package/corpus/templates/clips/app/i18n/pt-BR.ts +0 -9
- package/corpus/templates/clips/app/i18n/zh-CN.ts +0 -7
- package/corpus/templates/clips/app/i18n/zh-TW.ts +0 -7
- package/corpus/templates/clips/app/lib/capture-install-options.ts +21 -0
- package/corpus/templates/clips/app/lib/fmp4.ts +271 -0
- package/corpus/templates/clips/app/lib/mse-video-loader.ts +585 -0
- package/corpus/templates/clips/app/routes/_app.dictate.tsx +0 -4
- package/corpus/templates/clips/app/routes/_app.meetings.$meetingId.tsx +5 -13
- package/corpus/templates/clips/app/routes/_app.meetings._index.tsx +2 -37
- package/corpus/templates/clips/app/routes/download.tsx +3 -2
- package/corpus/templates/clips/changelog/2026-07-10-shared-clips-now-start-playing-instantly-instead-of-showing-.md +6 -0
- package/corpus/templates/clips/changelog/2026-07-14-clips-now-distinguishes-transcript-previews-from-incomplete-.md +6 -0
- package/corpus/templates/clips/changelog/2026-07-14-desktop-app-prompts-stay-hidden-after-you-download-the-insta.md +6 -0
- package/corpus/templates/clips/changelog/2026-07-14-share-dialogs-show-separate-links-for-people-and-agents.md +6 -0
- package/corpus/templates/clips/desktop/src/lib/recorder.ts +5 -0
- package/corpus/templates/clips/desktop/src/overlays/recording-pill.tsx +10 -0
- package/corpus/templates/clips/desktop/src-tauri/src/lib.rs +4 -0
- package/corpus/templates/clips/desktop/src-tauri/src/native_screen/custom_capture.rs +2518 -0
- package/corpus/templates/clips/desktop/src-tauri/src/native_screen/live_upload.rs +353 -0
- package/corpus/templates/clips/desktop/src-tauri/src/native_screen.rs +558 -67
- package/corpus/templates/clips/desktop/src-tauri/src/recording_indicator.rs +11 -1
- package/corpus/templates/clips/desktop/src-tauri/src/remote_flags.rs +188 -0
- package/corpus/templates/clips/desktop/src-tauri/src/whisper_speech.rs +1 -1
- package/corpus/templates/clips/server/lib/post-finalize-dispatch.ts +1 -0
- package/corpus/templates/clips/server/plugins/agent-chat.ts +5 -0
- package/corpus/templates/clips/server/routes/api/_agent-native-background/post-finalize-worker.post.ts +5 -1
- package/corpus/templates/clips/shared/feature-flags.ts +41 -0
- package/corpus/templates/design/.agents/skills/design-generation/SKILL.md +3 -0
- package/corpus/templates/design/.agents/skills/design-review-feedback/SKILL.md +42 -0
- package/corpus/templates/design/AGENTS.md +6 -0
- package/corpus/templates/design/README.md +1 -0
- package/corpus/templates/design/actions/navigate.ts +4 -4
- package/corpus/templates/design/actions/view-screen.ts +116 -2
- package/corpus/templates/design/agent-native.app-skill.json +5 -0
- package/corpus/templates/design/app/components/design/DesignCanvas.tsx +52 -59
- package/corpus/templates/design/app/components/design/DesignExtensionsPanel.tsx +13 -9
- package/corpus/templates/design/app/components/design/EditPanel.tsx +79 -11
- package/corpus/templates/design/app/components/design/LayersPanel.tsx +78 -65
- package/corpus/templates/design/app/components/design/ReviewCommentsPanel.tsx +161 -0
- package/corpus/templates/design/app/components/design/ReviewStatusControl.tsx +96 -0
- package/corpus/templates/design/app/components/design/bridge/hit-test.bridge.ts +166 -0
- package/corpus/templates/design/app/components/layout/Layout.tsx +1 -0
- package/corpus/templates/design/app/components/visual-editor/ReviewCanvasPins.tsx +1077 -0
- package/corpus/templates/design/app/components/visual-editor/index.ts +1 -0
- package/corpus/templates/design/app/components/visual-editor/review-canvas-state.ts +42 -0
- package/corpus/templates/design/app/hooks/use-design-systems.ts +2 -2
- package/corpus/templates/design/app/hooks/use-navigation-state.ts +9 -6
- package/corpus/templates/design/app/hooks/use-question-flow.ts +7 -1
- package/corpus/templates/design/app/i18n/ar-SA.ts +56 -1
- package/corpus/templates/design/app/i18n/de-DE.ts +57 -1
- package/corpus/templates/design/app/i18n/en-US.ts +56 -1
- package/corpus/templates/design/app/i18n/es-ES.ts +56 -1
- package/corpus/templates/design/app/i18n/fr-FR.ts +57 -1
- package/corpus/templates/design/app/i18n/hi-IN.ts +56 -1
- package/corpus/templates/design/app/i18n/ja-JP.ts +56 -1
- package/corpus/templates/design/app/i18n/ko-KR.ts +56 -1
- package/corpus/templates/design/app/i18n/pt-BR.ts +57 -1
- package/corpus/templates/design/app/i18n/zh-CN.ts +56 -1
- package/corpus/templates/design/app/i18n/zh-TW.ts +51 -0
- package/corpus/templates/design/app/pages/Present.tsx +172 -14
- package/corpus/templates/design/app/pages/design-editor/overview-camera.ts +23 -0
- package/corpus/templates/design/app/pages/design-editor/tool-state.ts +10 -0
- package/corpus/templates/design/app/pages/present-review-state.ts +18 -0
- package/corpus/templates/design/app/public-routes.ts +8 -0
- package/corpus/templates/design/app/root.tsx +7 -6
- package/corpus/templates/design/changelog/2026-07-13-dragged-design-assets-now-appear-at-the-visible-drop-locatio.md +6 -0
- package/corpus/templates/design/changelog/2026-07-13-reviewers-can-pin-comments-on-shared-designs-and-apply-verif.md +6 -0
- package/corpus/templates/design/server/plugins/agent-chat.ts +10 -0
- package/corpus/templates/design/server/plugins/auth.ts +7 -5
- package/corpus/templates/design/server/plugins/review.ts +9 -0
- package/corpus/templates/design/shared/review-anchor.ts +83 -0
- package/corpus/templates/design/shared/review-summary.ts +25 -0
- package/corpus/templates/dispatch/changelog/2026-07-14-dispatch-now-distinguishes-connected-agents-from-locally-mou.md +6 -0
- package/corpus/templates/forms/.agents/skills/form-publishing/SKILL.md +2 -0
- package/corpus/templates/forms/AGENTS.md +4 -0
- package/corpus/templates/forms/actions/create-form.ts +2 -1
- package/corpus/templates/forms/actions/update-form.ts +5 -2
- package/corpus/templates/forms/app/i18n/ar-SA.ts +3 -0
- package/corpus/templates/forms/app/i18n/de-DE.ts +3 -0
- package/corpus/templates/forms/app/i18n/en-US.ts +3 -0
- package/corpus/templates/forms/app/i18n/es-ES.ts +3 -0
- package/corpus/templates/forms/app/i18n/fr-FR.ts +3 -0
- package/corpus/templates/forms/app/i18n/hi-IN.ts +3 -0
- package/corpus/templates/forms/app/i18n/ja-JP.ts +3 -0
- package/corpus/templates/forms/app/i18n/ko-KR.ts +3 -0
- package/corpus/templates/forms/app/i18n/pt-BR.ts +3 -0
- package/corpus/templates/forms/app/i18n/zh-CN.ts +3 -0
- package/corpus/templates/forms/app/i18n/zh-TW.ts +3 -0
- package/corpus/templates/forms/app/pages/FormBuilderPage.tsx +19 -0
- package/corpus/templates/forms/changelog/2026-07-14-fixed-the-ask-forms-loading-input-appearing-above-the-welcom.md +6 -0
- package/corpus/templates/forms/changelog/2026-07-14-form-social-previews-now-show-the-form-title-description-and.md +6 -0
- package/corpus/templates/forms/changelog/2026-07-14-forms-can-email-the-form-owner-when-new-responses-arrive.md +6 -0
- package/corpus/templates/forms/server/handlers/submissions.ts +17 -0
- package/corpus/templates/forms/server/lib/form-og-image.ts +64 -6
- package/corpus/templates/forms/server/lib/public-form-ssr.ts +6 -2
- package/corpus/templates/forms/server/lib/response-email.ts +65 -0
- package/corpus/templates/forms/server/plugins/agent-chat.ts +1 -0
- package/corpus/templates/forms/server/routes/api/forms/og/[...slug]/og.png.get.ts +184 -0
- package/corpus/templates/forms/shared/types.ts +2 -0
- package/corpus/templates/plan/.agents/skills/visual-plan/SKILL.md +6 -4
- package/corpus/templates/plan/.agents/skills/visual-recap/SKILL.md +7 -1
- package/dist/a2a/index.d.ts +2 -1
- package/dist/a2a/index.d.ts.map +1 -1
- package/dist/a2a/index.js +1 -1
- package/dist/a2a/index.js.map +1 -1
- package/dist/a2a/server.d.ts +25 -0
- package/dist/a2a/server.d.ts.map +1 -1
- package/dist/a2a/server.js +30 -6
- package/dist/a2a/server.js.map +1 -1
- package/dist/agent/production-agent.d.ts +2 -0
- package/dist/agent/production-agent.d.ts.map +1 -1
- package/dist/agent/production-agent.js +37 -12
- package/dist/agent/production-agent.js.map +1 -1
- package/dist/cli/create.d.ts +5 -3
- package/dist/cli/create.d.ts.map +1 -1
- package/dist/cli/create.js +44 -19
- package/dist/cli/create.js.map +1 -1
- package/dist/cli/pr-visual-recap-workflow.d.ts +2 -2
- package/dist/cli/pr-visual-recap-workflow.d.ts.map +1 -1
- package/dist/cli/pr-visual-recap-workflow.js +2 -2
- package/dist/cli/pr-visual-recap-workflow.js.map +1 -1
- package/dist/cli/recap.d.ts +3 -562
- package/dist/cli/recap.d.ts.map +1 -1
- package/dist/cli/recap.js +3 -3875
- package/dist/cli/recap.js.map +1 -1
- package/dist/cli/skills-content/visual-plan-skill.d.ts +1 -1
- package/dist/cli/skills-content/visual-plan-skill.d.ts.map +1 -1
- package/dist/cli/skills-content/visual-plan-skill.js +6 -4
- package/dist/cli/skills-content/visual-plan-skill.js.map +1 -1
- package/dist/cli/skills-content/visual-recap-skill.d.ts +1 -1
- package/dist/cli/skills-content/visual-recap-skill.d.ts.map +1 -1
- package/dist/cli/skills-content/visual-recap-skill.js +7 -1
- package/dist/cli/skills-content/visual-recap-skill.js.map +1 -1
- package/dist/client/AgentPanel.d.ts.map +1 -1
- package/dist/client/AgentPanel.js +3 -3
- package/dist/client/AgentPanel.js.map +1 -1
- package/dist/client/analytics.d.ts +5 -0
- package/dist/client/analytics.d.ts.map +1 -1
- package/dist/client/analytics.js +3 -1
- package/dist/client/analytics.js.map +1 -1
- package/dist/client/chat/markdown-renderer.d.ts +1 -0
- package/dist/client/chat/markdown-renderer.d.ts.map +1 -1
- package/dist/client/chat/markdown-renderer.js +36 -1
- package/dist/client/chat/markdown-renderer.js.map +1 -1
- package/dist/client/chat/message-components.d.ts.map +1 -1
- package/dist/client/chat/message-components.js +5 -2
- package/dist/client/chat/message-components.js.map +1 -1
- package/dist/client/clipboard.d.ts +3 -1
- package/dist/client/clipboard.d.ts.map +1 -1
- package/dist/client/clipboard.js +24 -1
- package/dist/client/clipboard.js.map +1 -1
- package/dist/client/guided-questions.d.ts +3 -1
- package/dist/client/guided-questions.d.ts.map +1 -1
- package/dist/client/guided-questions.js +2 -1
- package/dist/client/guided-questions.js.map +1 -1
- package/dist/client/i18n.d.ts.map +1 -1
- package/dist/client/i18n.js +3 -1
- 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/review/ReviewCommentComposer.d.ts +18 -0
- package/dist/client/review/ReviewCommentComposer.d.ts.map +1 -0
- package/dist/client/review/ReviewCommentComposer.js +30 -0
- package/dist/client/review/ReviewCommentComposer.js.map +1 -0
- package/dist/client/review/ReviewThreadPanel.d.ts +28 -1
- package/dist/client/review/ReviewThreadPanel.d.ts.map +1 -1
- package/dist/client/review/ReviewThreadPanel.js +151 -39
- package/dist/client/review/ReviewThreadPanel.js.map +1 -1
- package/dist/client/review/index.d.ts +3 -2
- package/dist/client/review/index.d.ts.map +1 -1
- package/dist/client/review/index.js +2 -1
- package/dist/client/review/index.js.map +1 -1
- package/dist/client/review/use-review.d.ts +23 -0
- package/dist/client/review/use-review.d.ts.map +1 -1
- package/dist/client/review/use-review.js +3 -0
- package/dist/client/review/use-review.js.map +1 -1
- package/dist/client/use-agent-chat-context.d.ts +1 -1
- package/dist/client/use-agent-chat-context.d.ts.map +1 -1
- package/dist/client/use-agent-chat-context.js +4 -2
- package/dist/client/use-agent-chat-context.js.map +1 -1
- package/dist/collab/awareness.d.ts +2 -2
- package/dist/collab/awareness.d.ts.map +1 -1
- package/dist/collab/struct-routes.d.ts +1 -1
- package/dist/credentials/index.d.ts +12 -7
- package/dist/credentials/index.d.ts.map +1 -1
- package/dist/credentials/index.js +33 -8
- package/dist/credentials/index.js.map +1 -1
- package/dist/extensions/fetch-tool.d.ts +13 -1
- package/dist/extensions/fetch-tool.d.ts.map +1 -1
- package/dist/extensions/fetch-tool.js +9 -2
- package/dist/extensions/fetch-tool.js.map +1 -1
- package/dist/notifications/channels.js +20 -4
- package/dist/notifications/channels.js.map +1 -1
- package/dist/observability/routes.d.ts +5 -5
- package/dist/progress/routes.d.ts +1 -1
- package/dist/provider-api/corpus-jobs.d.ts +2 -2
- package/dist/resources/handlers.d.ts +3 -3
- package/dist/review/actions/create-review-comment.js +2 -1
- package/dist/review/actions/create-review-comment.js.map +1 -1
- package/dist/review/actions/get-review-feedback.js +6 -11
- package/dist/review/actions/get-review-feedback.js.map +1 -1
- package/dist/review/actions/list-review-comments.d.ts +1 -0
- package/dist/review/actions/list-review-comments.js +25 -4
- package/dist/review/actions/list-review-comments.js.map +1 -1
- package/dist/review/actions/reply-review-comment.js +12 -5
- package/dist/review/actions/reply-review-comment.js.map +1 -1
- package/dist/review/actions/resolve-review-thread.d.ts +3 -0
- package/dist/review/actions/resolve-review-thread.js +20 -3
- package/dist/review/actions/resolve-review-thread.js.map +1 -1
- package/dist/review/actions/send-review-thread-to-agent.d.ts +17 -0
- package/dist/review/actions/send-review-thread-to-agent.d.ts.map +1 -0
- package/dist/review/actions/send-review-thread-to-agent.js +49 -0
- package/dist/review/actions/send-review-thread-to-agent.js.map +1 -0
- package/dist/review/identity.d.ts +6 -0
- package/dist/review/identity.d.ts.map +1 -0
- package/dist/review/identity.js +68 -0
- package/dist/review/identity.js.map +1 -0
- package/dist/review/index.d.ts +3 -1
- package/dist/review/index.d.ts.map +1 -1
- package/dist/review/index.js +2 -1
- package/dist/review/index.js.map +1 -1
- package/dist/review/store.d.ts +36 -0
- package/dist/review/store.d.ts.map +1 -1
- package/dist/review/store.js +223 -8
- package/dist/review/store.js.map +1 -1
- package/dist/review/types.d.ts +4 -0
- package/dist/review/types.d.ts.map +1 -1
- package/dist/review/types.js.map +1 -1
- package/dist/secrets/crypto.d.ts +15 -7
- package/dist/secrets/crypto.d.ts.map +1 -1
- package/dist/secrets/crypto.js +23 -10
- package/dist/secrets/crypto.js.map +1 -1
- package/dist/secrets/routes.d.ts +9 -9
- package/dist/secrets/storage.d.ts.map +1 -1
- package/dist/secrets/storage.js +16 -3
- package/dist/secrets/storage.js.map +1 -1
- package/dist/server/action-discovery.d.ts.map +1 -1
- package/dist/server/action-discovery.js +4 -0
- package/dist/server/action-discovery.js.map +1 -1
- package/dist/server/action-routes.d.ts +45 -0
- package/dist/server/action-routes.d.ts.map +1 -1
- package/dist/server/action-routes.js +71 -5
- package/dist/server/action-routes.js.map +1 -1
- package/dist/server/agent-chat/plugin-options.d.ts +16 -0
- package/dist/server/agent-chat/plugin-options.d.ts.map +1 -1
- package/dist/server/agent-chat/plugin-options.js.map +1 -1
- package/dist/server/agent-chat-plugin.d.ts +20 -0
- package/dist/server/agent-chat-plugin.d.ts.map +1 -1
- package/dist/server/agent-chat-plugin.js +39 -4
- package/dist/server/agent-chat-plugin.js.map +1 -1
- package/dist/server/derived-secret.d.ts +1 -1
- package/dist/server/derived-secret.d.ts.map +1 -1
- package/dist/server/derived-secret.js.map +1 -1
- package/dist/server/index.d.ts +3 -1
- package/dist/server/index.d.ts.map +1 -1
- package/dist/server/index.js +2 -0
- package/dist/server/index.js.map +1 -1
- package/dist/vite/action-types-plugin.d.ts.map +1 -1
- package/dist/vite/action-types-plugin.js +4 -0
- package/dist/vite/action-types-plugin.js.map +1 -1
- package/docs/content/locales/ar-SA/pr-visual-recap.mdx +48 -30
- package/docs/content/locales/ar-SA/template-plan.mdx +7 -0
- package/docs/content/locales/de-DE/pr-visual-recap.mdx +48 -30
- package/docs/content/locales/de-DE/template-plan.mdx +7 -0
- package/docs/content/locales/es-ES/pr-visual-recap.mdx +48 -30
- package/docs/content/locales/es-ES/template-plan.mdx +14 -0
- package/docs/content/locales/fr-FR/pr-visual-recap.mdx +48 -30
- package/docs/content/locales/fr-FR/template-plan.mdx +7 -0
- package/docs/content/locales/hi-IN/pr-visual-recap.mdx +48 -30
- package/docs/content/locales/hi-IN/template-plan.mdx +7 -0
- package/docs/content/locales/ja-JP/pr-visual-recap.mdx +48 -30
- package/docs/content/locales/ja-JP/template-plan.mdx +7 -0
- package/docs/content/locales/ko-KR/pr-visual-recap.mdx +48 -30
- package/docs/content/locales/ko-KR/template-plan.mdx +7 -0
- package/docs/content/locales/pt-BR/pr-visual-recap.mdx +48 -30
- package/docs/content/locales/pt-BR/template-plan.mdx +14 -0
- package/docs/content/locales/zh-CN/pr-visual-recap.mdx +48 -30
- package/docs/content/locales/zh-CN/template-plan.mdx +7 -0
- package/docs/content/locales/zh-TW/pr-visual-recap.mdx +48 -30
- package/docs/content/locales/zh-TW/template-plan.mdx +7 -0
- package/docs/content/pr-visual-recap.mdx +50 -32
- package/docs/content/template-plan.mdx +14 -0
- package/docs/content/toolkit-comments-review.mdx +16 -2
- package/package.json +4 -1
- package/corpus/templates/clips/app/components/sharing/slack-share-hint.tsx +0 -68
- package/corpus/templates/forms/server/routes/api/forms/og/[slug]/og.png.get.ts +0 -45
|
@@ -7,7 +7,6 @@ import {
|
|
|
7
7
|
} from "@agent-native/core/client";
|
|
8
8
|
import {
|
|
9
9
|
IconCode,
|
|
10
|
-
IconChevronDown,
|
|
11
10
|
IconExternalLink,
|
|
12
11
|
IconLink,
|
|
13
12
|
IconMail,
|
|
@@ -33,13 +32,7 @@ import {
|
|
|
33
32
|
type SharesResponse,
|
|
34
33
|
type Visibility,
|
|
35
34
|
} from "@/components/sharing/share-ui";
|
|
36
|
-
import { SlackShareHint } from "@/components/sharing/slack-share-hint";
|
|
37
35
|
import { Button } from "@/components/ui/button";
|
|
38
|
-
import {
|
|
39
|
-
Collapsible,
|
|
40
|
-
CollapsibleContent,
|
|
41
|
-
CollapsibleTrigger,
|
|
42
|
-
} from "@/components/ui/collapsible";
|
|
43
36
|
import { Dialog, DialogContent, DialogTitle } from "@/components/ui/dialog";
|
|
44
37
|
import { Input } from "@/components/ui/input";
|
|
45
38
|
import { Label } from "@/components/ui/label";
|
|
@@ -317,7 +310,6 @@ function LinkTab({
|
|
|
317
310
|
const agentLinkRequestIdRef = useRef(0);
|
|
318
311
|
const [agentContextUrl, setAgentContextUrl] = useState("");
|
|
319
312
|
const [agentLinkError, setAgentLinkError] = useState(false);
|
|
320
|
-
const [agentShareOpen, setAgentShareOpen] = useState(false);
|
|
321
313
|
|
|
322
314
|
useEffect(() => {
|
|
323
315
|
createAgentLinkAsyncRef.current = createAgentLink.mutateAsync;
|
|
@@ -352,26 +344,22 @@ function LinkTab({
|
|
|
352
344
|
setAgentLinkError(false);
|
|
353
345
|
if (!sharesLoaded) return;
|
|
354
346
|
|
|
355
|
-
if (!isPublic
|
|
347
|
+
if (!isPublic) {
|
|
356
348
|
void loadAgentContextUrl();
|
|
357
349
|
}
|
|
358
350
|
|
|
359
351
|
return () => {
|
|
360
352
|
agentLinkRequestIdRef.current += 1;
|
|
361
353
|
};
|
|
362
|
-
}, [
|
|
363
|
-
agentShareOpen,
|
|
364
|
-
isPublic,
|
|
365
|
-
loadAgentContextUrl,
|
|
366
|
-
recordingId,
|
|
367
|
-
sharesLoaded,
|
|
368
|
-
visibility,
|
|
369
|
-
]);
|
|
354
|
+
}, [isPublic, loadAgentContextUrl, recordingId, sharesLoaded, visibility]);
|
|
370
355
|
|
|
356
|
+
const agentLink = isPublic ? shareUrl : agentContextUrl;
|
|
371
357
|
const agentShareDisabled =
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
358
|
+
visibilityPending ||
|
|
359
|
+
!sharesLoaded ||
|
|
360
|
+
(!isPublic && (isPending || createAgentLink.isPending || !agentContextUrl));
|
|
361
|
+
const agentPrompt = agentLink
|
|
362
|
+
? t("shareDialog.agentPrompt", { agentContextUrl: agentLink })
|
|
375
363
|
: "";
|
|
376
364
|
|
|
377
365
|
return (
|
|
@@ -399,67 +387,42 @@ function LinkTab({
|
|
|
399
387
|
}
|
|
400
388
|
/>
|
|
401
389
|
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
<
|
|
415
|
-
<
|
|
416
|
-
{t("shareDialog.
|
|
417
|
-
</
|
|
418
|
-
<
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
<div className="flex items-center justify-between gap-2 rounded-md border border-border bg-background px-3 py-2">
|
|
439
|
-
<p className="text-xs text-muted-foreground">
|
|
440
|
-
{t("shareDialog.agentLinkUnavailable")}
|
|
441
|
-
</p>
|
|
442
|
-
<Button
|
|
443
|
-
type="button"
|
|
444
|
-
variant="ghost"
|
|
445
|
-
size="sm"
|
|
446
|
-
className="h-7"
|
|
447
|
-
onClick={() => void loadAgentContextUrl()}
|
|
448
|
-
disabled={createAgentLink.isPending}
|
|
449
|
-
>
|
|
450
|
-
{t("shareDialog.retryAgentLink")}
|
|
451
|
-
</Button>
|
|
452
|
-
</div>
|
|
453
|
-
) : null}
|
|
454
|
-
<CopyField
|
|
455
|
-
label={t("shareDialog.copyAgentPrompt")}
|
|
456
|
-
value={agentPrompt}
|
|
457
|
-
disabled={agentShareDisabled}
|
|
458
|
-
/>
|
|
459
|
-
</div>
|
|
460
|
-
</CollapsibleContent>
|
|
461
|
-
</Collapsible>
|
|
462
|
-
) : null}
|
|
390
|
+
<div className="space-y-2">
|
|
391
|
+
<CopyField
|
|
392
|
+
label={t("shareDialog.shareWithAgents")}
|
|
393
|
+
value={agentLink}
|
|
394
|
+
disabled={agentShareDisabled}
|
|
395
|
+
/>
|
|
396
|
+
{sharesLoaded && !isPublic ? (
|
|
397
|
+
<>
|
|
398
|
+
<p className="text-xs text-muted-foreground">
|
|
399
|
+
{t("shareDialog.agentTokenDescription")}
|
|
400
|
+
</p>
|
|
401
|
+
{agentLinkError ? (
|
|
402
|
+
<div className="flex items-center justify-between gap-2 rounded-md border border-border bg-muted/30 px-3 py-2">
|
|
403
|
+
<p className="text-xs text-muted-foreground">
|
|
404
|
+
{t("shareDialog.agentLinkUnavailable")}
|
|
405
|
+
</p>
|
|
406
|
+
<Button
|
|
407
|
+
type="button"
|
|
408
|
+
variant="ghost"
|
|
409
|
+
size="sm"
|
|
410
|
+
className="h-7"
|
|
411
|
+
onClick={() => void loadAgentContextUrl()}
|
|
412
|
+
disabled={createAgentLink.isPending}
|
|
413
|
+
>
|
|
414
|
+
{t("shareDialog.retryAgentLink")}
|
|
415
|
+
</Button>
|
|
416
|
+
</div>
|
|
417
|
+
) : null}
|
|
418
|
+
<CopyField
|
|
419
|
+
label={t("shareDialog.copyAgentPrompt")}
|
|
420
|
+
value={agentPrompt}
|
|
421
|
+
disabled={agentShareDisabled}
|
|
422
|
+
/>
|
|
423
|
+
</>
|
|
424
|
+
) : null}
|
|
425
|
+
</div>
|
|
463
426
|
|
|
464
427
|
{sharesLoaded && !isPublic && canManage ? (
|
|
465
428
|
<MakePublicCard
|
|
@@ -28,6 +28,7 @@ import {
|
|
|
28
28
|
DropdownMenuTrigger,
|
|
29
29
|
} from "@/components/ui/dropdown-menu";
|
|
30
30
|
import { Spinner } from "@/components/ui/spinner";
|
|
31
|
+
import { useMseVideoSource } from "@/hooks/use-mse-video-source";
|
|
31
32
|
import {
|
|
32
33
|
parsePlaybackSpeed,
|
|
33
34
|
readPlaybackSpeedPreference,
|
|
@@ -365,6 +366,32 @@ export const VideoPlayer = forwardRef<VideoPlayerHandle, VideoPlayerProps>(
|
|
|
365
366
|
[resolvedVideoSrc],
|
|
366
367
|
);
|
|
367
368
|
|
|
369
|
+
// Media Source Extensions path for raw fragmented-MP4 recordings (desktop
|
|
370
|
+
// live-stream uploads). Those files declare no up-front duration, so the
|
|
371
|
+
// native progressive pipeline scans the whole file before it can play from
|
|
372
|
+
// a CDN. When the asset sniffs as fragmented, `mse.mode === "mse"` and we
|
|
373
|
+
// hand the element a MediaSource object URL instead of the raw URL, with the
|
|
374
|
+
// duration supplied from the DB. Everything else (classic MP4, WebM, Loom,
|
|
375
|
+
// browsers without MediaSource) stays on the native `<video src>` path,
|
|
376
|
+
// byte-for-byte unchanged.
|
|
377
|
+
const mse = useMseVideoSource({
|
|
378
|
+
videoRef,
|
|
379
|
+
sourceUrl: resolvedVideoSrc,
|
|
380
|
+
durationMs,
|
|
381
|
+
videoFormat,
|
|
382
|
+
disabled: isLoomEmbed || unsupportedFormat,
|
|
383
|
+
});
|
|
384
|
+
const mseActive = mse.mode === "mse" && Boolean(mse.objectUrl);
|
|
385
|
+
// The URL actually put on the <video> element: the MediaSource object URL
|
|
386
|
+
// while MSE drives playback, nothing while we're still sniffing an eligible
|
|
387
|
+
// asset (so the browser never starts the slow native scan), otherwise the
|
|
388
|
+
// normal resolved/cache-busted source.
|
|
389
|
+
const domVideoSrc = mseActive
|
|
390
|
+
? mse.objectUrl
|
|
391
|
+
: mse.mode === "pending"
|
|
392
|
+
? undefined
|
|
393
|
+
: activeVideoSrc;
|
|
394
|
+
|
|
368
395
|
useEffect(() => {
|
|
369
396
|
if (!resolvedVideoSrc) {
|
|
370
397
|
setActiveVideoSrc(undefined);
|
|
@@ -1164,7 +1191,7 @@ export const VideoPlayer = forwardRef<VideoPlayerHandle, VideoPlayerProps>(
|
|
|
1164
1191
|
) : activeVideoSrc ? (
|
|
1165
1192
|
<video
|
|
1166
1193
|
ref={videoRef}
|
|
1167
|
-
src={
|
|
1194
|
+
src={domVideoSrc}
|
|
1168
1195
|
poster={resolveLocalUrl(thumbnailUrl)}
|
|
1169
1196
|
// `crossOrigin` is only needed so the owner's canvas thumbnail
|
|
1170
1197
|
// capture isn't tainted. For everyone else (viewers, and the Slack
|
|
@@ -1328,6 +1355,17 @@ export const VideoPlayer = forwardRef<VideoPlayerHandle, VideoPlayerProps>(
|
|
|
1328
1355
|
playAttemptPendingRef.current = false;
|
|
1329
1356
|
setIsPlayPending(false);
|
|
1330
1357
|
|
|
1358
|
+
// If the MSE pipeline surfaced a media error, tear it down and let
|
|
1359
|
+
// the native <video src> path take over the raw asset URL instead
|
|
1360
|
+
// of running the cache-bust retry against a MediaSource blob URL.
|
|
1361
|
+
if (mseActive) {
|
|
1362
|
+
mse.fallbackToNative();
|
|
1363
|
+
setIsBuffering(false);
|
|
1364
|
+
setIsPreparing(true);
|
|
1365
|
+
setCanPlay(false);
|
|
1366
|
+
return;
|
|
1367
|
+
}
|
|
1368
|
+
|
|
1331
1369
|
// Most "format not supported" / decode errors reported here are
|
|
1332
1370
|
// transient — e.g. the share page's video element started
|
|
1333
1371
|
// fetching a moment before a background seekable-remux pass
|
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
import { useCallback, useEffect, useState } from "react";
|
|
2
2
|
|
|
3
3
|
import { useIsMobile } from "@/hooks/use-mobile";
|
|
4
|
-
|
|
5
|
-
|
|
4
|
+
import {
|
|
5
|
+
hasDownloadedDesktopApp,
|
|
6
|
+
markDesktopAppDownloaded,
|
|
7
|
+
} from "@/lib/capture-install-options";
|
|
6
8
|
|
|
7
9
|
function detectDesktopApp(): boolean {
|
|
8
10
|
if (typeof navigator === "undefined") return false;
|
|
@@ -25,20 +27,12 @@ export function useDesktopPromo() {
|
|
|
25
27
|
|
|
26
28
|
useEffect(() => {
|
|
27
29
|
setIsDesktopApp(detectDesktopApp());
|
|
28
|
-
setDismissed(
|
|
29
|
-
typeof window !== "undefined" &&
|
|
30
|
-
window.localStorage?.getItem(DISMISSED_KEY) === "1",
|
|
31
|
-
);
|
|
30
|
+
setDismissed(hasDownloadedDesktopApp());
|
|
32
31
|
}, []);
|
|
33
32
|
|
|
34
33
|
const dismiss = useCallback(() => {
|
|
35
34
|
setDismissed(true);
|
|
36
|
-
|
|
37
|
-
window.localStorage?.setItem(DISMISSED_KEY, "1");
|
|
38
|
-
} catch {
|
|
39
|
-
// localStorage can throw in private browsing — ignore, dismissal
|
|
40
|
-
// still holds for the session via React state.
|
|
41
|
-
}
|
|
35
|
+
markDesktopAppDownloaded();
|
|
42
36
|
}, []);
|
|
43
37
|
|
|
44
38
|
return {
|
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Decides whether a recording should play through Media Source Extensions and,
|
|
3
|
+
* when it should, owns the `MseVideoLoader` lifecycle.
|
|
4
|
+
*
|
|
5
|
+
* Raw fragmented-MP4 recordings (from the desktop live-streaming pipeline)
|
|
6
|
+
* declare no up-front duration, so the browser's progressive `<video src>`
|
|
7
|
+
* pipeline stalls when they're served from a CDN. This hook sniffs the asset,
|
|
8
|
+
* and for fragmented files hands the video element a `MediaSource` object URL
|
|
9
|
+
* driven by range requests with the duration supplied from the DB. Classic MP4,
|
|
10
|
+
* WebM, Loom, and anything the browser can't MSE fall back to the native path
|
|
11
|
+
* unchanged.
|
|
12
|
+
*/
|
|
13
|
+
|
|
14
|
+
import {
|
|
15
|
+
type RefObject,
|
|
16
|
+
useCallback,
|
|
17
|
+
useEffect,
|
|
18
|
+
useRef,
|
|
19
|
+
useState,
|
|
20
|
+
} from "react";
|
|
21
|
+
|
|
22
|
+
import { sniffFragmentedMp4 } from "@/lib/fmp4";
|
|
23
|
+
import { MseVideoLoader, isMediaSourceSupported } from "@/lib/mse-video-loader";
|
|
24
|
+
|
|
25
|
+
export type MseSourceMode = "pending" | "native" | "mse";
|
|
26
|
+
|
|
27
|
+
export interface UseMseVideoSourceParams {
|
|
28
|
+
videoRef: RefObject<HTMLVideoElement | null>;
|
|
29
|
+
/** The resolved asset URL (proxied same-origin or provider URL). */
|
|
30
|
+
sourceUrl: string | undefined;
|
|
31
|
+
/** Authoritative duration in ms from the DB. */
|
|
32
|
+
durationMs: number;
|
|
33
|
+
/** Container format hint. WebM is never eligible for this MP4-only loader. */
|
|
34
|
+
videoFormat?: "webm" | "mp4" | null;
|
|
35
|
+
/** True for Loom embeds / formats the browser cannot decode — never MSE. */
|
|
36
|
+
disabled?: boolean;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
export interface UseMseVideoSourceResult {
|
|
40
|
+
mode: MseSourceMode;
|
|
41
|
+
/** MediaSource object URL to use as `<video src>` when `mode === "mse"`. */
|
|
42
|
+
objectUrl: string | undefined;
|
|
43
|
+
/** Drop MSE and revert to the plain `<video src>` path. */
|
|
44
|
+
fallbackToNative: () => void;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
export function useMseVideoSource({
|
|
48
|
+
videoRef,
|
|
49
|
+
sourceUrl,
|
|
50
|
+
durationMs,
|
|
51
|
+
videoFormat,
|
|
52
|
+
disabled,
|
|
53
|
+
}: UseMseVideoSourceParams): UseMseVideoSourceResult {
|
|
54
|
+
// WebM recordings use the native Infinity-duration workaround; only MP4 (and
|
|
55
|
+
// unknown-format, which the sniff will confirm) are candidates.
|
|
56
|
+
const eligible =
|
|
57
|
+
!disabled &&
|
|
58
|
+
!!sourceUrl &&
|
|
59
|
+
videoFormat !== "webm" &&
|
|
60
|
+
isMediaSourceSupported();
|
|
61
|
+
|
|
62
|
+
const [mode, setMode] = useState<MseSourceMode>(() =>
|
|
63
|
+
eligible ? "pending" : "native",
|
|
64
|
+
);
|
|
65
|
+
const [objectUrl, setObjectUrl] = useState<string | undefined>(undefined);
|
|
66
|
+
const loaderRef = useRef<MseVideoLoader | null>(null);
|
|
67
|
+
|
|
68
|
+
// Latest duration, kept in a ref so the (deliberately duration-independent)
|
|
69
|
+
// rebuild effect below seeds a freshly created loader with the current value
|
|
70
|
+
// even if it changed during the async sniff. Updating a ref in render is
|
|
71
|
+
// side-effect-free and safe.
|
|
72
|
+
const durationMsRef = useRef(durationMs);
|
|
73
|
+
durationMsRef.current = durationMs;
|
|
74
|
+
|
|
75
|
+
useEffect(() => {
|
|
76
|
+
loaderRef.current?.destroy();
|
|
77
|
+
loaderRef.current = null;
|
|
78
|
+
setObjectUrl(undefined);
|
|
79
|
+
|
|
80
|
+
if (!eligible || !sourceUrl) {
|
|
81
|
+
setMode("native");
|
|
82
|
+
return;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
setMode("pending");
|
|
86
|
+
let cancelled = false;
|
|
87
|
+
|
|
88
|
+
void sniffFragmentedMp4(sourceUrl)
|
|
89
|
+
.then((isFragmented) => {
|
|
90
|
+
if (cancelled) return;
|
|
91
|
+
const video = videoRef.current;
|
|
92
|
+
if (!isFragmented || !video) {
|
|
93
|
+
setMode("native");
|
|
94
|
+
return;
|
|
95
|
+
}
|
|
96
|
+
try {
|
|
97
|
+
const loader = new MseVideoLoader({
|
|
98
|
+
url: sourceUrl,
|
|
99
|
+
durationMs: durationMsRef.current,
|
|
100
|
+
video,
|
|
101
|
+
onFatal: () => {
|
|
102
|
+
if (cancelled) return;
|
|
103
|
+
loaderRef.current?.destroy();
|
|
104
|
+
loaderRef.current = null;
|
|
105
|
+
setObjectUrl(undefined);
|
|
106
|
+
setMode("native");
|
|
107
|
+
},
|
|
108
|
+
});
|
|
109
|
+
loaderRef.current = loader;
|
|
110
|
+
setObjectUrl(loader.objectUrl);
|
|
111
|
+
setMode("mse");
|
|
112
|
+
} catch {
|
|
113
|
+
setMode("native");
|
|
114
|
+
}
|
|
115
|
+
})
|
|
116
|
+
.catch(() => {
|
|
117
|
+
if (!cancelled) setMode("native");
|
|
118
|
+
});
|
|
119
|
+
|
|
120
|
+
return () => {
|
|
121
|
+
cancelled = true;
|
|
122
|
+
loaderRef.current?.destroy();
|
|
123
|
+
loaderRef.current = null;
|
|
124
|
+
};
|
|
125
|
+
// videoRef is a stable ref object. `durationMs` is intentionally excluded:
|
|
126
|
+
// it only seeds the timeline and is pushed to the live loader by the effect
|
|
127
|
+
// below, so a metadata-poll update must not rebuild the loader (which would
|
|
128
|
+
// revoke the object URL and restart playback from byte zero).
|
|
129
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
130
|
+
}, [eligible, sourceUrl]);
|
|
131
|
+
|
|
132
|
+
// Recording metadata polling can raise the DB duration while the same
|
|
133
|
+
// fragmented asset is still playing; apply it to the live loader in place.
|
|
134
|
+
useEffect(() => {
|
|
135
|
+
loaderRef.current?.setDuration(durationMs);
|
|
136
|
+
}, [durationMs]);
|
|
137
|
+
|
|
138
|
+
const fallbackToNative = useCallback(() => {
|
|
139
|
+
loaderRef.current?.destroy();
|
|
140
|
+
loaderRef.current = null;
|
|
141
|
+
setObjectUrl(undefined);
|
|
142
|
+
setMode("native");
|
|
143
|
+
}, []);
|
|
144
|
+
|
|
145
|
+
return { mode, objectUrl, fallbackToNative };
|
|
146
|
+
}
|
|
@@ -887,14 +887,6 @@ const messages = {
|
|
|
887
887
|
"سيفقد {{email}} الوصول إلى هذه المؤسسة. يمكنك دائمًا دعوته مرة أخرى.",
|
|
888
888
|
remove: "إزالة",
|
|
889
889
|
},
|
|
890
|
-
slackShareHint: {
|
|
891
|
-
playsInline: "يعمل داخل Slack",
|
|
892
|
-
connectedDescription:
|
|
893
|
-
"الصق هذا الرابط في أي مساحة عمل متصلة لتشغيله داخلها.",
|
|
894
|
-
makeInline: "اجعله يعمل داخل Slack",
|
|
895
|
-
connectDescription: "قم بتوصيل مساحة عمل حتى يظهر هذا الرابط كفيديو.",
|
|
896
|
-
connect: "اتصال",
|
|
897
|
-
},
|
|
898
890
|
commentsPanel: {
|
|
899
891
|
disabled: "تم تعطيل التعليقات لهذا التسجيل.",
|
|
900
892
|
beFirst: "كن أول من يعلق",
|
|
@@ -911,15 +911,6 @@ Alle sichtbaren Änderungen für Clips-Nutzer werden hier dokumentiert. Du kanns
|
|
|
911
911
|
"{{email}} verliert den Zugriff auf diese Organisation. Du kannst die Person jederzeit erneut einladen.",
|
|
912
912
|
remove: "Entfernen",
|
|
913
913
|
},
|
|
914
|
-
slackShareHint: {
|
|
915
|
-
playsInline: "Wird inline in Slack abgespielt",
|
|
916
|
-
connectedDescription:
|
|
917
|
-
"Füge diesen Link in einem verbundenen Workspace ein, um ihn inline abzuspielen.",
|
|
918
|
-
makeInline: "Inline-Wiedergabe in Slack aktivieren",
|
|
919
|
-
connectDescription:
|
|
920
|
-
"Verbinde einen Workspace, damit dieser Link als Video angezeigt wird.",
|
|
921
|
-
connect: "Verbinden",
|
|
922
|
-
},
|
|
923
914
|
commentsPanel: {
|
|
924
915
|
disabled: "Kommentare sind für diese Aufzeichnung deaktiviert.",
|
|
925
916
|
beFirst: "Schreibe den ersten Kommentar",
|
|
@@ -882,14 +882,6 @@ All notable user-facing changes to Clips are documented here. Open it any time f
|
|
|
882
882
|
"{{email}} will lose access to this organization. You can always invite them back.",
|
|
883
883
|
remove: "Remove",
|
|
884
884
|
},
|
|
885
|
-
slackShareHint: {
|
|
886
|
-
playsInline: "Plays inline in Slack",
|
|
887
|
-
connectedDescription:
|
|
888
|
-
"Paste this link in any connected workspace to play it inline.",
|
|
889
|
-
makeInline: "Make it play inline in Slack",
|
|
890
|
-
connectDescription: "Connect a workspace so this link unfurls as a video.",
|
|
891
|
-
connect: "Connect",
|
|
892
|
-
},
|
|
893
885
|
commentsPanel: {
|
|
894
886
|
disabled: "Comments are disabled for this recording.",
|
|
895
887
|
beFirst: "Be the first to comment",
|
|
@@ -904,15 +904,6 @@ Todos los cambios visibles para los usuarios de Clips se documentan aquí. Puede
|
|
|
904
904
|
"{{email}} perderá acceso a esta organización. Siempre puedes volver a invitarlo.",
|
|
905
905
|
remove: "Eliminar",
|
|
906
906
|
},
|
|
907
|
-
slackShareHint: {
|
|
908
|
-
playsInline: "Se reproduce inline en Slack",
|
|
909
|
-
connectedDescription:
|
|
910
|
-
"Pega este enlace en cualquier espacio conectado para reproducirlo inline.",
|
|
911
|
-
makeInline: "Haz que se reproduzca inline en Slack",
|
|
912
|
-
connectDescription:
|
|
913
|
-
"Conecta un espacio para que este enlace se despliegue como video.",
|
|
914
|
-
connect: "Conectar",
|
|
915
|
-
},
|
|
916
907
|
commentsPanel: {
|
|
917
908
|
disabled: "Los comentarios están desactivados para esta grabación.",
|
|
918
909
|
beFirst: "Sé la primera persona en comentar",
|
|
@@ -906,15 +906,6 @@ Tous les changements visibles par les utilisateurs de Clips sont documentés ici
|
|
|
906
906
|
"{{email}} perdra l’accès à cette organisation. Vous pourrez toujours l’inviter à nouveau.",
|
|
907
907
|
remove: "Retirer",
|
|
908
908
|
},
|
|
909
|
-
slackShareHint: {
|
|
910
|
-
playsInline: "Lecture inline dans Slack",
|
|
911
|
-
connectedDescription:
|
|
912
|
-
"Collez ce lien dans n’importe quel espace connecté pour le lire inline.",
|
|
913
|
-
makeInline: "Le lire inline dans Slack",
|
|
914
|
-
connectDescription:
|
|
915
|
-
"Connectez un espace pour que ce lien se déplie en vidéo.",
|
|
916
|
-
connect: "Connecter",
|
|
917
|
-
},
|
|
918
909
|
commentsPanel: {
|
|
919
910
|
disabled: "Les commentaires sont désactivés pour cet enregistrement.",
|
|
920
911
|
beFirst: "Soyez le premier à commenter",
|
|
@@ -876,14 +876,6 @@ Clips में उपयोगकर्ताओं को दिखने व
|
|
|
876
876
|
"{{email}} इस संगठन तक पहुंच खो देगा। आप उन्हें हमेशा वापस आमंत्रित कर सकते हैं।",
|
|
877
877
|
remove: "हटाएं",
|
|
878
878
|
},
|
|
879
|
-
slackShareHint: {
|
|
880
|
-
playsInline: "Slack में इनलाइन चलता है",
|
|
881
|
-
connectedDescription:
|
|
882
|
-
"इसे इनलाइन चलाने के लिए यह लिंक किसी भी जुड़े हुए वर्कस्पेस में पेस्ट करें।",
|
|
883
|
-
makeInline: "इसे Slack में इनलाइन चलाएं",
|
|
884
|
-
connectDescription: "एक वर्कस्पेस कनेक्ट करें ताकि यह लिंक वीडियो के रूप में खुले।",
|
|
885
|
-
connect: "कनेक्ट करें",
|
|
886
|
-
},
|
|
887
879
|
commentsPanel: {
|
|
888
880
|
disabled: "इस रिकॉर्डिंग के लिए टिप्पणियां बंद हैं।",
|
|
889
881
|
beFirst: "पहली टिप्पणी करें",
|
|
@@ -893,15 +893,6 @@ Clips のユーザー向けの主な変更はここに記録されます。コ
|
|
|
893
893
|
"{{email}} はこの組織へのアクセスを失います。いつでも再招待できます。",
|
|
894
894
|
remove: "削除",
|
|
895
895
|
},
|
|
896
|
-
slackShareHint: {
|
|
897
|
-
playsInline: "Slack 内でインライン再生",
|
|
898
|
-
connectedDescription:
|
|
899
|
-
"このリンクを接続済みワークスペースに貼り付けるとインライン再生されます。",
|
|
900
|
-
makeInline: "Slack でインライン再生する",
|
|
901
|
-
connectDescription:
|
|
902
|
-
"ワークスペースを接続すると、このリンクが動画として展開されます。",
|
|
903
|
-
connect: "接続",
|
|
904
|
-
},
|
|
905
896
|
commentsPanel: {
|
|
906
897
|
disabled: "この録画ではコメントが無効です。",
|
|
907
898
|
beFirst: "最初にコメントする",
|
|
@@ -883,15 +883,6 @@ Clips의 모든 사용자 대상 변경 사항은 여기에 기록됩니다. 명
|
|
|
883
883
|
"{{email}}은 이 조직에 대한 액세스 권한을 잃습니다. 언제든 다시 초대할 수 있습니다.",
|
|
884
884
|
remove: "제거",
|
|
885
885
|
},
|
|
886
|
-
slackShareHint: {
|
|
887
|
-
playsInline: "Slack에서 인라인 재생",
|
|
888
|
-
connectedDescription:
|
|
889
|
-
"이 링크를 연결된 워크스페이스에 붙여넣으면 인라인으로 재생됩니다.",
|
|
890
|
-
makeInline: "Slack에서 인라인 재생하기",
|
|
891
|
-
connectDescription:
|
|
892
|
-
"워크스페이스를 연결하면 이 링크가 동영상으로 펼쳐집니다.",
|
|
893
|
-
connect: "연결",
|
|
894
|
-
},
|
|
895
886
|
commentsPanel: {
|
|
896
887
|
disabled: "이 녹화에서는 댓글이 비활성화되어 있습니다.",
|
|
897
888
|
beFirst: "첫 댓글을 남겨보세요",
|
|
@@ -900,15 +900,6 @@ Todas as mudanças visíveis para usuários do Clips são documentadas aqui. Voc
|
|
|
900
900
|
"{{email}} perderá acesso a esta organização. Você sempre pode convidá-lo novamente.",
|
|
901
901
|
remove: "Remover",
|
|
902
902
|
},
|
|
903
|
-
slackShareHint: {
|
|
904
|
-
playsInline: "Reproduz inline no Slack",
|
|
905
|
-
connectedDescription:
|
|
906
|
-
"Cole este link em qualquer workspace conectado para reproduzi-lo inline.",
|
|
907
|
-
makeInline: "Faça reproduzir inline no Slack",
|
|
908
|
-
connectDescription:
|
|
909
|
-
"Conecte um workspace para que este link abra como vídeo.",
|
|
910
|
-
connect: "Conectar",
|
|
911
|
-
},
|
|
912
903
|
commentsPanel: {
|
|
913
904
|
disabled: "Os comentários estão desativados para esta gravação.",
|
|
914
905
|
beFirst: "Seja a primeira pessoa a comentar",
|
|
@@ -849,13 +849,6 @@ Clips 中所有面向用户的重要更改都会记录在这里。你可以随
|
|
|
849
849
|
"{{email}} 将失去对此组织的访问权限。你随时可以重新邀请他们。",
|
|
850
850
|
remove: "移除",
|
|
851
851
|
},
|
|
852
|
-
slackShareHint: {
|
|
853
|
-
playsInline: "可在 Slack 中内联播放",
|
|
854
|
-
connectedDescription: "将此链接粘贴到任何已连接工作区即可内联播放。",
|
|
855
|
-
makeInline: "让它在 Slack 中内联播放",
|
|
856
|
-
connectDescription: "连接一个工作区,让此链接展开为视频。",
|
|
857
|
-
connect: "连接",
|
|
858
|
-
},
|
|
859
852
|
commentsPanel: {
|
|
860
853
|
disabled: "此录制已禁用评论。",
|
|
861
854
|
beFirst: "成为第一个评论的人",
|
|
@@ -842,13 +842,6 @@ const messages = {
|
|
|
842
842
|
"{{email}} 將失去對此組織的存取權限。你隨時可以重新邀請他們。",
|
|
843
843
|
remove: "移除",
|
|
844
844
|
},
|
|
845
|
-
slackShareHint: {
|
|
846
|
-
playsInline: "可在 Slack 中行內播放",
|
|
847
|
-
connectedDescription: "將此連結貼上到任何已連線工作區即可行內播放。",
|
|
848
|
-
makeInline: "讓它在 Slack 中行內播放",
|
|
849
|
-
connectDescription: "連線一個工作區,讓此連結展開為影片。",
|
|
850
|
-
connect: "連線",
|
|
851
|
-
},
|
|
852
845
|
commentsPanel: {
|
|
853
846
|
disabled: "此錄製已停用評論。",
|
|
854
847
|
beFirst: "成為第一個評論的人",
|
|
@@ -1,3 +1,24 @@
|
|
|
1
|
+
const DESKTOP_DOWNLOAD_STORAGE_KEY = "clips.desktop-promo.dismissed";
|
|
2
|
+
|
|
3
|
+
export function hasDownloadedDesktopApp(): boolean {
|
|
4
|
+
try {
|
|
5
|
+
return (
|
|
6
|
+
typeof window !== "undefined" &&
|
|
7
|
+
window.localStorage?.getItem(DESKTOP_DOWNLOAD_STORAGE_KEY) === "1"
|
|
8
|
+
);
|
|
9
|
+
} catch {
|
|
10
|
+
return false;
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export function markDesktopAppDownloaded(): void {
|
|
15
|
+
try {
|
|
16
|
+
window.localStorage?.setItem(DESKTOP_DOWNLOAD_STORAGE_KEY, "1");
|
|
17
|
+
} catch {
|
|
18
|
+
// Download tracking is best-effort and must not block the installer.
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
|
|
1
22
|
function isFalsy(value: unknown): boolean {
|
|
2
23
|
if (typeof value !== "string") return false;
|
|
3
24
|
return ["0", "false", "no", "off"].includes(value.trim().toLowerCase());
|