diff --git a/src/components/ai-edition/v4/V4Timeline.geometry.test.tsx b/src/components/ai-edition/v4/V4Timeline.geometry.test.tsx index f3a067bca..d237428f5 100644 --- a/src/components/ai-edition/v4/V4Timeline.geometry.test.tsx +++ b/src/components/ai-edition/v4/V4Timeline.geometry.test.tsx @@ -64,7 +64,7 @@ function clip(startSec: number, endSec: number) { } /** The asset every clip above points at. No `cameraTrack`: this recording has no webcam, - * which is what the Full Camera button is gated on. */ + * which is what Add Full Camera is gated on. */ const NO_CAMERA_ASSET = { id: "a1", label: "rec", durationSec: TOTAL_SEC }; /** By default one 30-minute clip carrying a single one-second annotation. */ @@ -221,29 +221,11 @@ describe("V4Timeline create-from-toolbar", () => { expect(durationOf(tl)).toBeCloseTo(0.25, 3); }); - // #353. A camera-fullscreen region grows the webcam overlay, so with no webcam on the - // timeline it renders nothing in the preview and nothing in the export — the region is - // stored and forgotten. `addCameraFullscreen` now refuses to write one; the button says - // so before it is clicked instead of looking like it worked. - it("disables Add Full Camera when no clip on the timeline has a camera", () => { - renderTimeline(); - expect(screen.getByTitle("buttons.addCameraFullscreen")).toBeDisabled(); - }); - - it("enables Add Full Camera as soon as a clip's asset carries one", () => { - renderTimeline(undefined, undefined, [ - { - ...NO_CAMERA_ASSET, - cameraTrack: { sourcePath: "/tmp/cam.webm", startMs: 0, offsetMs: 0, visible: true }, - }, - ]); - expect(screen.getByTitle("buttons.addCameraFullscreen")).toBeEnabled(); - }); - - // The disabled button is only half the promise: an empty lane advertises the shortcut - // that fills it, so on a camera-less project it was still inviting a `C` press that - // `addCameraFullscreen` now refuses. It borrows the Layout pane's "No Webcam" wording - // instead, so the two surfaces agree about the same project. + // The toolbar button is gone, but Add Full Camera is still reachable via the `C` + // shortcut, and an empty lane advertises it — so on a camera-less project it was + // still inviting a `C` press that `addCameraFullscreen` refuses (#353). It borrows + // the Layout pane's "No Webcam" wording instead, so the two surfaces agree about + // the same project. it("does not advertise the C shortcut on a lane that cannot be filled", () => { renderTimeline(); expect(screen.getByText("layout.noWebcam")).toBeInTheDocument(); diff --git a/src/components/ai-edition/v4/V4Timeline.tsx b/src/components/ai-edition/v4/V4Timeline.tsx index 493f17d5c..a6300bb47 100644 --- a/src/components/ai-edition/v4/V4Timeline.tsx +++ b/src/components/ai-edition/v4/V4Timeline.tsx @@ -431,9 +431,9 @@ export function V4Timeline({ const clips = tl.clips; // A camera-fullscreen region grows the webcam overlay, so on a project with no webcam // it renders nothing in the preview and nothing in the export. `addCameraFullscreen` - // refuses to write one (see useTimeline) — this makes the control say so before it is - // clicked instead of looking like it worked. Same question, same helper as the Layout - // pane: is a camera attached anywhere on this timeline? + // refuses to write one (see useTimeline) — this is why the empty lane's hint below + // swaps to "no webcam" instead of advertising the `C` shortcut. Same question, same + // helper as the Layout pane: is a camera attached anywhere on this timeline? const hasAnyCamera = useMemo(() => hasAnyClipWithCamera(tl.assets, clips), [tl.assets, clips]); const total = useMemo( () => @@ -1359,17 +1359,6 @@ export function V4Timeline({ > - ) : ( // Media is an ARRANGING surface: add, remove, reorder. Nothing here @@ -1463,8 +1452,7 @@ export function V4Timeline({
{renderPills(zoomPills, t("hints.pressZoom"))}
{/* Advertising "Press C" on a project with no webcam invites a keystroke - that `addCameraFullscreen` now refuses (#353). The toolbar button is - already disabled; this keeps the lane from contradicting it. */} + that `addCameraFullscreen` now refuses (#353). */} {renderPills( cameraFullscreenPills, hasAnyCamera ? t("hints.pressCameraFullscreen") : ts("layout.noWebcam"), diff --git a/src/i18n/locales/ar/timeline.json b/src/i18n/locales/ar/timeline.json index 4412a0a0b..e434620eb 100644 --- a/src/i18n/locales/ar/timeline.json +++ b/src/i18n/locales/ar/timeline.json @@ -8,8 +8,7 @@ "autoFocusAllOff": "تفعيل التركيز التلقائي لجميع التكبيرات (الكاميرا تتبع المؤشر)", "addTrim": "إضافة قص (T)", "addAnnotation": "إضافة شرح (A)", - "addSpeed": "إضافة سرعة (S)", - "addCameraFullscreen": "إضافة كاميرا كاملة الشاشة (C)" + "addSpeed": "إضافة سرعة (S)" }, "hints": { "pressZoom": "اضغط Z لإضافة تكبير", diff --git a/src/i18n/locales/en/timeline.json b/src/i18n/locales/en/timeline.json index c41966115..cd15921ef 100644 --- a/src/i18n/locales/en/timeline.json +++ b/src/i18n/locales/en/timeline.json @@ -8,8 +8,7 @@ "autoFocusAllOff": "Auto-Focus all zooms (camera follows the cursor)", "addTrim": "Add Trim (T)", "addAnnotation": "Add Annotation (A)", - "addSpeed": "Add Speed (S)", - "addCameraFullscreen": "Add Full Camera (C)" + "addSpeed": "Add Speed (S)" }, "hints": { "pressZoom": "Press Z to add zoom", diff --git a/src/i18n/locales/es/timeline.json b/src/i18n/locales/es/timeline.json index 989289e00..c05eebf89 100644 --- a/src/i18n/locales/es/timeline.json +++ b/src/i18n/locales/es/timeline.json @@ -8,8 +8,7 @@ "autoFocusAllOff": "Activar enfoque automático para todos los zooms (la cámara sigue el cursor)", "addTrim": "Agregar recorte (T)", "addAnnotation": "Agregar anotación (A)", - "addSpeed": "Agregar velocidad (S)", - "addCameraFullscreen": "Agregar cámara a pantalla completa (C)" + "addSpeed": "Agregar velocidad (S)" }, "hints": { "pressZoom": "Presiona Z para agregar zoom", diff --git a/src/i18n/locales/fr/timeline.json b/src/i18n/locales/fr/timeline.json index a35b8858a..3147db21d 100644 --- a/src/i18n/locales/fr/timeline.json +++ b/src/i18n/locales/fr/timeline.json @@ -8,8 +8,7 @@ "autoFocusAllOff": "Activer la mise au point automatique pour tous les zooms (la caméra suit le curseur)", "addTrim": "Ajouter une coupe (T)", "addAnnotation": "Ajouter une annotation (A)", - "addSpeed": "Ajouter une vitesse (S)", - "addCameraFullscreen": "Ajouter Caméra plein écran (C)" + "addSpeed": "Ajouter une vitesse (S)" }, "hints": { "pressZoom": "Appuyez sur Z pour ajouter un zoom", diff --git a/src/i18n/locales/it/timeline.json b/src/i18n/locales/it/timeline.json index 09bb116ee..468764831 100644 --- a/src/i18n/locales/it/timeline.json +++ b/src/i18n/locales/it/timeline.json @@ -8,8 +8,7 @@ "autoFocusAllOff": "Attiva la messa a fuoco automatica per tutti gli zoom (la fotocamera segue il cursore)", "addTrim": "Aggiungi taglio (T)", "addAnnotation": "Aggiungi annotazione (A)", - "addSpeed": "Aggiungi velocità (S)", - "addCameraFullscreen": "Aggiungi Camera a schermo intero (C)" + "addSpeed": "Aggiungi velocità (S)" }, "hints": { "pressZoom": "Premi Z per aggiungere zoom", diff --git a/src/i18n/locales/ja-JP/timeline.json b/src/i18n/locales/ja-JP/timeline.json index 68911ba91..7ebcc6b36 100644 --- a/src/i18n/locales/ja-JP/timeline.json +++ b/src/i18n/locales/ja-JP/timeline.json @@ -8,8 +8,7 @@ "autoFocusAllOff": "すべてのズームでオートフォーカスをオンにする(カメラがカーソルに追従)", "addTrim": "トリムを追加 (T)", "addAnnotation": "注釈を追加 (A)", - "addSpeed": "再生速度を追加 (S)", - "addCameraFullscreen": "フルスクリーンカメラを追加 (C)" + "addSpeed": "再生速度を追加 (S)" }, "hints": { "pressZoom": "Zキーを押してズームを追加", diff --git a/src/i18n/locales/ko-KR/timeline.json b/src/i18n/locales/ko-KR/timeline.json index 8a100ee6d..986d173ce 100644 --- a/src/i18n/locales/ko-KR/timeline.json +++ b/src/i18n/locales/ko-KR/timeline.json @@ -8,8 +8,7 @@ "autoFocusAllOff": "모든 줌에 자동 초점 켜기 (카메라가 커서를 따라갑니다)", "addTrim": "트림 추가 (T)", "addAnnotation": "주석 추가 (A)", - "addSpeed": "속도 추가 (S)", - "addCameraFullscreen": "전체 화면 카메라 추가 (C)" + "addSpeed": "속도 추가 (S)" }, "hints": { "pressZoom": "Z를 눌러 줌 추가", diff --git a/src/i18n/locales/pt-BR/timeline.json b/src/i18n/locales/pt-BR/timeline.json index 5359feba9..ed9c42bd7 100644 --- a/src/i18n/locales/pt-BR/timeline.json +++ b/src/i18n/locales/pt-BR/timeline.json @@ -8,8 +8,7 @@ "autoFocusAllOff": "Ativar foco automático para todos os zooms (a câmera segue o cursor)", "addTrim": "Adicionar Recorte (T)", "addAnnotation": "Adicionar Anotação (A)", - "addSpeed": "Adicionar Velocidade (S)", - "addCameraFullscreen": "Adicionar Câmera em Tela Cheia (C)" + "addSpeed": "Adicionar Velocidade (S)" }, "hints": { "pressZoom": "Pressione Z para adicionar zoom", diff --git a/src/i18n/locales/ru/timeline.json b/src/i18n/locales/ru/timeline.json index 387086953..9ce1261fb 100644 --- a/src/i18n/locales/ru/timeline.json +++ b/src/i18n/locales/ru/timeline.json @@ -8,8 +8,7 @@ "autoFocusAllOff": "Включить автофокус для всех зумов (камера следует за курсором)", "addTrim": "Добавить обрезку (T)", "addAnnotation": "Добавить аннотацию (A)", - "addSpeed": "Изменить скорость (S)", - "addCameraFullscreen": "Добавить камеру на весь экран (C)" + "addSpeed": "Изменить скорость (S)" }, "hints": { "pressZoom": "Нажмите Z для добавления масштабирования", diff --git a/src/i18n/locales/tr/timeline.json b/src/i18n/locales/tr/timeline.json index d5a531f3e..c56c0613b 100644 --- a/src/i18n/locales/tr/timeline.json +++ b/src/i18n/locales/tr/timeline.json @@ -8,8 +8,7 @@ "autoFocusAllOff": "Tüm yakınlaştırmalarda Otomatik Odağı aç (kamera imleci takip eder)", "addTrim": "Kırpma Ekle (T)", "addAnnotation": "Açıklama Ekle (A)", - "addSpeed": "Hız Ekle (S)", - "addCameraFullscreen": "Tam Ekran Kamera Ekle (C)" + "addSpeed": "Hız Ekle (S)" }, "hints": { "pressZoom": "Yakınlaştırma eklemek için Z tuşuna basın", diff --git a/src/i18n/locales/vi/timeline.json b/src/i18n/locales/vi/timeline.json index 1d963e585..fe6011b27 100644 --- a/src/i18n/locales/vi/timeline.json +++ b/src/i18n/locales/vi/timeline.json @@ -8,8 +8,7 @@ "autoFocusAllOff": "Bật lấy nét tự động cho tất cả các thu phóng (máy ảnh theo dõi con trỏ)", "addTrim": "Thêm Cắt (T)", "addAnnotation": "Thêm Chú thích (A)", - "addSpeed": "Thêm Tốc độ (S)", - "addCameraFullscreen": "Thêm Camera Toàn màn hình (C)" + "addSpeed": "Thêm Tốc độ (S)" }, "hints": { "pressZoom": "Nhấn Z để thêm thu phóng", diff --git a/src/i18n/locales/zh-CN/timeline.json b/src/i18n/locales/zh-CN/timeline.json index 1451e6d31..bd405fa89 100644 --- a/src/i18n/locales/zh-CN/timeline.json +++ b/src/i18n/locales/zh-CN/timeline.json @@ -8,8 +8,7 @@ "autoFocusAllOff": "为所有缩放开启自动对焦(摄像头跟随光标)", "addTrim": "添加剪辑 (T)", "addAnnotation": "添加标注 (A)", - "addSpeed": "添加速度 (S)", - "addCameraFullscreen": "添加全屏摄像头 (C)" + "addSpeed": "添加速度 (S)" }, "hints": { "pressZoom": "按 Z 添加缩放", diff --git a/src/i18n/locales/zh-TW/timeline.json b/src/i18n/locales/zh-TW/timeline.json index 7f4ba9874..6692ad24a 100644 --- a/src/i18n/locales/zh-TW/timeline.json +++ b/src/i18n/locales/zh-TW/timeline.json @@ -8,8 +8,7 @@ "autoFocusAllOff": "為所有縮放開啟自動對焦(攝影機跟隨游標)", "addTrim": "新增剪輯 (T)", "addAnnotation": "新增標註 (A)", - "addSpeed": "新增速度 (S)", - "addCameraFullscreen": "新增全螢幕攝影機 (C)" + "addSpeed": "新增速度 (S)" }, "hints": { "pressZoom": "按 Z 新增縮放", diff --git a/src/lib/ai-edition/store/useTimeline.ts b/src/lib/ai-edition/store/useTimeline.ts index 7823459ec..67f2ecdfb 100644 --- a/src/lib/ai-edition/store/useTimeline.ts +++ b/src/lib/ai-edition/store/useTimeline.ts @@ -407,9 +407,9 @@ export function useTimeline() { // a missing `webcamRect`) and nothing in the export — it just sits in // `legacyEditor.cameraFullscreenRegions` forever. The agent's `addCameraFullscreen` // tool already refuses this and says why (electron/ai-edition/agent-tools.ts, - // `noCameraUnderSpan`); the gate lives HERE rather than at each button so both UI - // entry points — the toolbar and the `C` shortcut — and any future one are covered - // by construction. `hasAnyClipWithCamera` is the consolidated answer to "does this + // `noCameraUnderSpan`); the gate lives HERE rather than at each caller so the `C` + // shortcut and any future entry point are covered by construction. + // `hasAnyClipWithCamera` is the consolidated answer to "does this // project have a camera at all", used the same way by the Layout pane. const addCameraFullscreen = useCallback( async (durationSec = DEFAULT_NEW_REGION_SEC) => {