From 9bb857b4b6ef0bcbd624e4d5a4bea957b635343c Mon Sep 17 00:00:00 2001 From: Sarosh Aga Date: Tue, 7 Jul 2026 11:46:45 +0400 Subject: [PATCH 1/2] Enable the Highlights video style for all users The Highlights video style previously shipped as a disabled "Coming Soon" card, unlocked only in development mode. This makes it available to everyone alongside Cinematic: the style is selectable, uses its real preview image, and no longer depends on a development-only override. Also removes the now-unused "coming soon" teaser asset and updates the style-picker tests to cover the always-available behavior. Co-Authored-By: Claude Opus 4.8 Claude-Session: https://claude.ai/code/session_01QCeR9xAHZbWvSmS4vpvW3W --- .../assets/video/styles/highlights-soon.webp | Bin 6028 -> 0 bytes .../components/style-picker/index.test.tsx | 37 ++++-------------- .../src/components/style-picker/index.tsx | 29 ++------------ 3 files changed, 10 insertions(+), 56 deletions(-) delete mode 100644 packages/image-studio/src/assets/video/styles/highlights-soon.webp diff --git a/packages/image-studio/src/assets/video/styles/highlights-soon.webp b/packages/image-studio/src/assets/video/styles/highlights-soon.webp deleted file mode 100644 index 920fa0ed114b130e8d051e15240db6fec279115b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6028 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≦̸wb23Q4LbB*P>R{eq<`<14Pj-;vU0xby0{ zz*SQJI7sfO)dK_f6YLrUy0R^1n*QG6gY*36dE)XP7o1Pc%IW!8@=k9(WJ$=oA8)um zk*UXuXP5`CzZD1Fe+9qvg$@=OU+OmdZONqmYH|Zfoxz8}~;3eXZ!^iu8k zOd#}BR(#P9=_kYYlFk_jHg1?;|u#uv;bd zZS%^R+xOMkq+gY5Gah`&<1M>c)g2>{t#*4TBem$$XGwFkXlKnBap43!Sv{BpOgRl} zc^B-TQ#%gOA7d2#UKlLQrkxb8>etK+0^dk}`{9VRW0Z8FhUi5ZXENd3bG1=IMMWjb zg~@+|p?+7fWBc4@ofW2ePCXZE6=5oxNAquoruIMuK3)AVuBHi*eHv^HY}9XiD;pYd zqH3{5H4t~n$P^+*;+QX)wPiR;0XnD0X{8(~CBwe1ilnqRdbd|9%z7C^{RF#pH%E5a zEivB+dU4<6TN@hvI=JMCt`($^?1bPpaAe@4UrO=CMJijOVjO*EzR-}VPpc5L5o#4n zs-F=@o88eaN#4V=#B<5f%&R7LOyM8#!I8v!@n{?Jv_ftm{)Y)RY5Tb%c9mL?dYBR= z=o6_7Lf@O|weVMM{(GmP5)E^$-gMmCK`bW+v&aU5a%j zSJln@3y9nGM0;_#y^_ndU8_nzhM1%fbDL*t-0>*%cX<{+`CMKXy}+NC#Aib2?zrgr ztOR7Am{eaHGpcGpqEqR4wECLUSfbam%DmLr_E!%nb{=V}ZfDcRq}1yt87qU>!RVtO z);%)cGaH%LWJTF1CRc%W@jjqgSjBA~ajZVlI`X6}A%{AfAY;*^As_UjT_Q-JIo!>1 zPjsnf=FmmG>r(QT6T=go;8+bzFT0doW-mj)#L$Zgfjn#7$}TB0D|FhEwHm~r`v;Wy zlLVTC!(!~hkAz|e)~b%R;rV+pxQirtSNM88TqojNOD9}IA#g8#zrdJGzO<}tCd&o2 z7}q|4Di%sddcQ>~^NK1BAG+SUR~{VQrp { } ); } ); - it( 'exports Cinematic (active) + Highlights (disabled teaser) video styles', () => { + it( 'exports Cinematic + Highlights video styles, both active', () => { expect( VIDEO_STYLE_OPTIONS ).toHaveLength( 2 ); expect( VIDEO_STYLE_OPTIONS[ 0 ] ).toMatchObject( { @@ -446,10 +446,10 @@ describe( 'StylePicker', () => { expect( VIDEO_STYLE_OPTIONS[ 0 ].preview ).toBeTruthy(); expect( VIDEO_STYLE_OPTIONS[ 1 ] ).toMatchObject( { - label: 'Highlights (Coming Soon)', + label: 'Highlights', value: 'highlights', - disabled: true, } ); + expect( VIDEO_STYLE_OPTIONS[ 1 ].disabled ).toBeFalsy(); expect( VIDEO_STYLE_OPTIONS[ 1 ].preview ).toBeTruthy(); } ); @@ -467,16 +467,6 @@ describe( 'StylePicker', () => { expect( dropdown ).not.toHaveTextContent( 'Pixel Art' ); } ); - it( 'renders the disabled video style as an inert (native-disabled) card', async () => { - const user = userEvent.setup(); - render( ); - - await user.click( screen.getByTestId( 'toolbar-button' ) ); - const dropdown = screen.getByTestId( 'dropdown-content' ); - const highlightsCard = within( dropdown ).getByRole( 'button', { name: /Highlights/ } ); - expect( highlightsCard ).toBeDisabled(); - } ); - it( 'maps style values correctly', async () => { const user = userEvent.setup(); @@ -514,23 +504,9 @@ describe( 'StylePicker', () => { } ); } ); - describe( 'Dev-mode Highlights gating', () => { - it( 'keeps Highlights disabled with the Coming Soon teaser when isDevMode is unset', async () => { - const user = userEvent.setup(); - render( ); - - await user.click( screen.getByTestId( 'toolbar-button' ) ); - const dropdown = screen.getByTestId( 'dropdown-content' ); - const highlightsCard = within( dropdown ).getByRole( 'button', { name: /Highlights/ } ); - - expect( highlightsCard ).toBeDisabled(); - expect( highlightsCard ).toHaveTextContent( 'Highlights (Coming Soon)' ); - } ); - - it( 'unlocks Highlights with the a12s label, enabled card, and a preview when isDevMode is true', async () => { + describe( 'Highlights video style', () => { + it( 'shows Highlights as an enabled option with a preview for all users', async () => { const user = userEvent.setup(); - ( window as Record< string, unknown > ).imageStudioData = { isDevMode: true }; - render( ); await user.click( screen.getByTestId( 'toolbar-button' ) ); @@ -538,7 +514,8 @@ describe( 'StylePicker', () => { const highlightsCard = within( dropdown ).getByRole( 'button', { name: /Highlights/ } ); expect( highlightsCard ).not.toBeDisabled(); - expect( highlightsCard ).toHaveTextContent( 'Highlights (a12s only)' ); + expect( highlightsCard ).toHaveTextContent( 'Highlights' ); + expect( highlightsCard ).not.toHaveTextContent( 'Coming Soon' ); expect( highlightsCard.querySelector( 'img' ) ).toBeInTheDocument(); } ); } ); diff --git a/packages/image-studio/src/components/style-picker/index.tsx b/packages/image-studio/src/components/style-picker/index.tsx index dc24d9026931..c69e5a92c5d7 100644 --- a/packages/image-studio/src/components/style-picker/index.tsx +++ b/packages/image-studio/src/components/style-picker/index.tsx @@ -19,7 +19,6 @@ import photographicPreview from '../../assets/photographic.webp'; import pixelArtPreview from '../../assets/pixel-art.webp'; import texturePreview from '../../assets/texture.webp'; import videoCinematicPreview from '../../assets/video/styles/cinematic.webp'; -import videoHighlightsSoonPreview from '../../assets/video/styles/highlights-soon.webp'; import videoHighlightsPreview from '../../assets/video/styles/highlights.webp'; import vividPreview from '../../assets/vivid.webp'; import { store as imageStudioStore } from '../../store'; @@ -140,11 +139,6 @@ export const STYLE_OPTIONS: StyleOption[] = [ // (LLM-composed HTML → EditFrame /api/v1/renders → MP4 → media library); // the in-browser encoding implementation lives on the older compositor // branches and is preserved there. -// -// Production default ships Cinematic-only; Highlights is disabled with a -// "coming soon" preview. The StylePicker component swaps in the live -// preview and enables the card when window.imageStudioData.isDevMode is -// true (a12s testing). export const VIDEO_STYLE_OPTIONS: StyleOption[] = [ { label: __( 'Cinematic', __i18n_text_domain__ ), @@ -153,14 +147,13 @@ export const VIDEO_STYLE_OPTIONS: StyleOption[] = [ description: __( 'Create an 8-second b-roll mood clip from a prompt.', __i18n_text_domain__ ), }, { - label: __( 'Highlights (Coming Soon)', __i18n_text_domain__ ), + label: __( 'Highlights', __i18n_text_domain__ ), value: 'highlights', - preview: videoHighlightsSoonPreview, + preview: videoHighlightsPreview, description: __( "Build a 20-second recap clip using your post's images and key points.", __i18n_text_domain__ ), - disabled: true, }, ]; @@ -180,23 +173,7 @@ export function StylePicker( { disabled = false, mode, variant = 'image' }: Styl [ targetStore ] ); - // Dev-mode override: unlock Highlights, swap to the live preview, and - // flip the label to "(a12s only)". Production default keeps the - // "Coming Soon" label + teaser preview + disabled state while we - // launch Cinematic-only. - const isDevMode = typeof window !== 'undefined' && window.imageStudioData?.isDevMode === true; - const options = isVideo - ? VIDEO_STYLE_OPTIONS.map( ( opt ) => - opt.value === 'highlights' && isDevMode - ? { - ...opt, - label: __( 'Highlights (a12s only)', __i18n_text_domain__ ), - preview: videoHighlightsPreview, - disabled: false, - } - : opt - ) - : STYLE_OPTIONS; + const options = isVideo ? VIDEO_STYLE_OPTIONS : STYLE_OPTIONS; const handleStyleSelect = ( value: string ) => { setSelectedStyle( value ); From 0bbf98c8d0d90788a63930d5ebcc46d77c3a13a2 Mon Sep 17 00:00:00 2001 From: Sarosh Aga Date: Tue, 7 Jul 2026 15:43:05 +0400 Subject: [PATCH 2/2] Silence no-require-imports for the jest.mock React require The style-picker test's jest.mock factory uses require('react') (jest hoisting). The branch code-style check lints the whole file now that it's touched, so add the repo-standard inline disable. Co-Authored-By: Claude Opus 4.8 Claude-Session: https://claude.ai/code/session_01QCeR9xAHZbWvSmS4vpvW3W --- packages/image-studio/src/components/style-picker/index.test.tsx | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/image-studio/src/components/style-picker/index.test.tsx b/packages/image-studio/src/components/style-picker/index.test.tsx index a40ec2fd6e0e..33fff64d9f36 100644 --- a/packages/image-studio/src/components/style-picker/index.test.tsx +++ b/packages/image-studio/src/components/style-picker/index.test.tsx @@ -4,6 +4,7 @@ import { render, screen, waitFor, within } from '@testing-library/react'; import userEvent from '@testing-library/user-event'; // Mock dependencies - MUST be before imports that use them jest.mock( '@automattic/agenttic-ui', () => { + // eslint-disable-next-line @typescript-eslint/no-require-imports const React = require( 'react' ); const { useState } = React;