diff --git a/apps/studio/src/components/content-tab-assistant.tsx b/apps/studio/src/components/content-tab-assistant.tsx index 72cc36d471..b13625d2c3 100644 --- a/apps/studio/src/components/content-tab-assistant.tsx +++ b/apps/studio/src/components/content-tab-assistant.tsx @@ -20,7 +20,6 @@ import { StudioCodeChat } from 'src/components/studio-code-chat'; import WelcomeComponent from 'src/components/welcome-message-prompt'; import { LIMIT_OF_PROMPTS_PER_USER, TELEX_HOSTNAME, TELEX_UTM_PARAMS } from 'src/constants'; import { useAuth } from 'src/hooks/use-auth'; -import { useFeatureFlags } from 'src/hooks/use-feature-flags'; import { useOffline } from 'src/hooks/use-offline'; import { useThemeDetails } from 'src/hooks/use-theme-details'; import { cx } from 'src/lib/cx'; @@ -359,7 +358,9 @@ const UnauthenticatedView = ( { onAuthenticate }: { onAuthenticate: () => void } ); export function ContentTabAssistant( { selectedSite }: ContentTabAssistantProps ) { - const { enableStudioCodeUi } = useFeatureFlags(); + const enableStudioCodeUi = useRootSelector( + ( state ) => state.betaFeatures.features.enableStudioCodeUi + ); if ( enableStudioCodeUi ) { return ; diff --git a/apps/studio/src/components/tests/content-tab-settings.test.tsx b/apps/studio/src/components/tests/content-tab-settings.test.tsx index 058a4fba1e..477c6069ea 100644 --- a/apps/studio/src/components/tests/content-tab-settings.test.tsx +++ b/apps/studio/src/components/tests/content-tab-settings.test.tsx @@ -38,7 +38,9 @@ const snapshotTestActions = { let testStore = createTestStore( { preloadedState: { betaFeatures: { - features: {}, + features: { + enableStudioCodeUi: false, + }, loading: false, }, }, @@ -49,7 +51,9 @@ function createCustomTestStore() { const store = createTestStore( { preloadedState: { betaFeatures: { - features: {}, + features: { + enableStudioCodeUi: false, + }, loading: false, }, }, diff --git a/apps/studio/src/ipc-types.d.ts b/apps/studio/src/ipc-types.d.ts index f57b868f55..659d80dc07 100644 --- a/apps/studio/src/ipc-types.d.ts +++ b/apps/studio/src/ipc-types.d.ts @@ -99,11 +99,11 @@ type IpcApi = { interface FeatureFlags { enableBlueprints: boolean; - enableStudioCodeUi: boolean; } -// eslint-disable-next-line @typescript-eslint/no-empty-object-type -interface BetaFeatures {} +interface BetaFeatures { + enableStudioCodeUi: boolean; +} interface AppGlobals extends FeatureFlags { platform: NodeJS.Platform; diff --git a/apps/studio/src/lib/beta-features.ts b/apps/studio/src/lib/beta-features.ts index a7770bbc3a..7a9d3b58b0 100644 --- a/apps/studio/src/lib/beta-features.ts +++ b/apps/studio/src/lib/beta-features.ts @@ -1,3 +1,4 @@ +import { __ } from '@wordpress/i18n'; import { lockAppdata, unlockAppdata, loadUserData, saveUserData } from 'src/storage/user-data'; export interface BetaFeatureDefinition { @@ -10,14 +11,23 @@ export interface BetaFeatureDefinition { /** * Default values for beta features. */ -const BETA_FEATURE_DEFAULTS: Record< keyof BetaFeatures, boolean > = {}; +const BETA_FEATURE_DEFAULTS: Record< keyof BetaFeatures, boolean > = { + enableStudioCodeUi: false, +}; /** * Returns beta feature definitions with translated labels and descriptions. * Must be called at runtime (not at module load) to ensure translations are loaded. */ export function getBetaFeaturesDefinition(): Record< keyof BetaFeatures, BetaFeatureDefinition > { - return {}; + return { + enableStudioCodeUi: { + label: __( 'Studio Code Desktop' ), + key: 'enableStudioCodeUi', + default: false, + description: __( 'Try the new Studio Code Desktop assistant.' ), + }, + }; } function buildBetaFeatures( userData: BetaFeatures | undefined ): BetaFeatures { @@ -26,7 +36,7 @@ function buildBetaFeatures( userData: BetaFeatures | undefined ): BetaFeatures { keys.forEach( ( key ) => { features[ key ] = userData?.[ key ] ?? BETA_FEATURE_DEFAULTS[ key ]; } ); - return features; + return features as BetaFeatures; } export async function getBetaFeatures(): Promise< BetaFeatures > { @@ -42,8 +52,6 @@ export async function updateBetaFeature( await lockAppdata(); const userData = await loadUserData(); const betaFeatures = await getBetaFeatures(); - // @ts-expect-error If `BetaFeatures` is empty, `key` will be `never`, and we cannot use it to - // assign to`betaFeatures`.That's fine. Just rely on type checking when this function is called. betaFeatures[ key ] = value; userData.betaFeatures = betaFeatures; await saveUserData( userData ); diff --git a/apps/studio/src/lib/feature-flags.ts b/apps/studio/src/lib/feature-flags.ts index a1bd010661..3cadfca0b8 100644 --- a/apps/studio/src/lib/feature-flags.ts +++ b/apps/studio/src/lib/feature-flags.ts @@ -12,12 +12,6 @@ export const FEATURE_FLAGS: Record< keyof FeatureFlags, FeatureFlagDefinition > flag: 'enableBlueprints', default: true, }, - enableStudioCodeUi: { - label: 'Enable Studio Code UI', - env: 'ENABLE_STUDIO_CODE_UI', - flag: 'enableStudioCodeUi', - default: false, - }, } as const; export function getFeatureFlagFromEnv( flag: keyof FeatureFlags ): boolean { diff --git a/apps/studio/src/menu.ts b/apps/studio/src/menu.ts index 76e8283e51..8332694797 100644 --- a/apps/studio/src/menu.ts +++ b/apps/studio/src/menu.ts @@ -164,7 +164,7 @@ async function getAppMenu( { label: __( 'Beta Features' ), submenu: betaFeaturesMenu, - enabled: false, + enabled: betaFeaturesMenu.length > 0, }, { type: 'separator' }, ...( process.platform === 'win32' diff --git a/apps/studio/src/stores/beta-features-slice.ts b/apps/studio/src/stores/beta-features-slice.ts index 3106844b25..cc21457ae6 100644 --- a/apps/studio/src/stores/beta-features-slice.ts +++ b/apps/studio/src/stores/beta-features-slice.ts @@ -8,7 +8,9 @@ type BetaFeaturesState = { }; const initialState: BetaFeaturesState = { - features: {}, + features: { + enableStudioCodeUi: false, + }, loading: false, };