diff --git a/projects/js-packages/ai-client/changelog/change-jetpack-ai-fetch-error-retry-optional b/projects/js-packages/ai-client/changelog/change-jetpack-ai-fetch-error-retry-optional new file mode 100644 index 0000000000000..22ca3f2a46ba9 --- /dev/null +++ b/projects/js-packages/ai-client/changelog/change-jetpack-ai-fetch-error-retry-optional @@ -0,0 +1,4 @@ +Significance: minor +Type: changed + +AI Client: make reload handler prop optional as it still works in a fuzzy way. The error notice (modal) will instruct to reload the page when the optional prop is not provided diff --git a/projects/js-packages/ai-client/changelog/fix-jetpack-ai-default-initial-state-setting b/projects/js-packages/ai-client/changelog/fix-jetpack-ai-default-initial-state-setting new file mode 100644 index 0000000000000..41efeee76f1f9 --- /dev/null +++ b/projects/js-packages/ai-client/changelog/fix-jetpack-ai-default-initial-state-setting @@ -0,0 +1,4 @@ +Significance: minor +Type: fixed + +AI Client: fix initial state being mapped even when fetch fails, making the default state nonsensical diff --git a/projects/js-packages/ai-client/src/logo-generator/components/feature-fetch-failure-screen.tsx b/projects/js-packages/ai-client/src/logo-generator/components/feature-fetch-failure-screen.tsx index cd1f53acdf38c..3404e7c1fbb0b 100644 --- a/projects/js-packages/ai-client/src/logo-generator/components/feature-fetch-failure-screen.tsx +++ b/projects/js-packages/ai-client/src/logo-generator/components/feature-fetch-failure-screen.tsx @@ -10,25 +10,34 @@ import type React from 'react'; export const FeatureFetchFailureScreen: React.FC< { onCancel: () => void; - onRetry: () => void; + onRetry?: () => void; } > = ( { onCancel, onRetry } ) => { const errorMessage = __( 'We are sorry. There was an error loading your Jetpack AI plan data. Please, try again.', 'jetpack-ai-client' ); + const errorMessageWithoutRetry = __( + 'We are sorry. There was an error loading your Jetpack AI plan data. Please, reload the page and try again.', + 'jetpack-ai-client' + ); + return (
- { errorMessage } + + { onRetry ? errorMessage : errorMessageWithoutRetry } +
- + { onRetry && ( + + ) }
); diff --git a/projects/js-packages/ai-client/src/logo-generator/components/generator-modal.tsx b/projects/js-packages/ai-client/src/logo-generator/components/generator-modal.tsx index 518a2014015e7..dfba25feb65fa 100644 --- a/projects/js-packages/ai-client/src/logo-generator/components/generator-modal.tsx +++ b/projects/js-packages/ai-client/src/logo-generator/components/generator-modal.tsx @@ -45,7 +45,7 @@ export const GeneratorModal: React.FC< GeneratorModalProps > = ( { isOpen, onClose, onApplyLogo, - onReload, + onReload = null, siteDetails, context, placement, @@ -73,7 +73,8 @@ export const GeneratorModal: React.FC< GeneratorModalProps > = ( { site, requireUpgrade, } = useLogoGenerator(); - const { featureFetchError, firstLogoPromptFetchError, clearErrors } = useRequestErrors(); + const { featureFetchError, setFeatureFetchError, firstLogoPromptFetchError, clearErrors } = + useRequestErrors(); const siteId = siteDetails?.ID; const [ logoAccepted, setLogoAccepted ] = useState( false ); const { nextTierCheckoutURL: upgradeURL } = useCheckout(); @@ -105,6 +106,15 @@ export const GeneratorModal: React.FC< GeneratorModalProps > = ( { */ const initializeModal = useCallback( async () => { try { + if ( ! siteId ) { + throw new Error( 'Site ID is missing' ); + } + + if ( ! feature?.featuresControl?.[ 'logo-generator' ]?.enabled ) { + setFeatureFetchError( 'Failed to fetch feature data' ); + throw new Error( 'Failed to fetch feature data' ); + } + const hasHistory = ! isLogoHistoryEmpty( String( siteId ) ); const logoCost = feature?.costs?.[ 'jetpack-ai-logo-generator' ]?.logo ?? DEFAULT_LOGO_COST; @@ -125,10 +135,10 @@ export const GeneratorModal: React.FC< GeneratorModalProps > = ( { : currentLimit < currentUsage ); // If the site requires an upgrade, show the upgrade screen immediately. - setNeedsFeature( currentLimit === 0 ); + setNeedsFeature( currentValue === 0 ); setNeedsMoreRequests( siteNeedsMoreRequests ); - if ( currentLimit === 0 || siteNeedsMoreRequests ) { + if ( currentValue === 0 || siteNeedsMoreRequests ) { setLoadingState( null ); return; } @@ -179,6 +189,7 @@ export const GeneratorModal: React.FC< GeneratorModalProps > = ( { isLogoHistoryEmpty, siteId, requireUpgrade, + setFeatureFetchError, ] ); const handleModalOpen = useCallback( async () => { @@ -201,6 +212,15 @@ export const GeneratorModal: React.FC< GeneratorModalProps > = ( { recordTracksEvent( EVENT_MODAL_CLOSE, { context, placement } ); }; + const handleReload = useCallback( () => { + if ( ! onReload ) { + return; + } + closeModal(); + requestedFeatureData.current = false; + onReload(); + }, [ onReload, closeModal ] ); + const handleApplyLogo = ( mediaId: number ) => { setLogoAccepted( true ); onApplyLogo?.( mediaId ); @@ -229,7 +249,7 @@ export const GeneratorModal: React.FC< GeneratorModalProps > = ( { // Handles modal opening logic useEffect( () => { // While the modal is not open, the siteId is not set, or the feature data is not available, do nothing. - if ( ! isOpen || ! siteId || ! feature?.costs ) { + if ( ! isOpen ) { return; } @@ -238,7 +258,7 @@ export const GeneratorModal: React.FC< GeneratorModalProps > = ( { needsToHandleModalOpen.current = false; handleModalOpen(); } - }, [ isOpen, siteId, handleModalOpen, feature ] ); + }, [ isOpen, handleModalOpen ] ); let body: React.ReactNode; @@ -248,10 +268,7 @@ export const GeneratorModal: React.FC< GeneratorModalProps > = ( { body = ( { - closeModal(); - onReload?.(); - } } + onRetry={ onReload ? handleReload : null } /> ); } else if ( needsFeature || needsMoreRequests ) { diff --git a/projects/js-packages/ai-client/src/logo-generator/components/prompt.scss b/projects/js-packages/ai-client/src/logo-generator/components/prompt.scss index 56d94215d5ff5..6a73d069a1bb6 100644 --- a/projects/js-packages/ai-client/src/logo-generator/components/prompt.scss +++ b/projects/js-packages/ai-client/src/logo-generator/components/prompt.scss @@ -69,7 +69,7 @@ color: var(--studio-gray-50, #646970); } - &[data-placeholder]:empty:focus::before { + &[data-placeholder]:empty:focus::before:not([contentEditable="false"]) { content: ""; } } diff --git a/projects/js-packages/ai-client/src/logo-generator/components/prompt.tsx b/projects/js-packages/ai-client/src/logo-generator/components/prompt.tsx index 55b77ae099ece..643bd0e3eb9fa 100644 --- a/projects/js-packages/ai-client/src/logo-generator/components/prompt.tsx +++ b/projects/js-packages/ai-client/src/logo-generator/components/prompt.tsx @@ -107,7 +107,7 @@ export const Prompt = ( { initialPrompt = '' }: PromptProps ) => { }, [ prompt ] ); useEffect( () => { - if ( imageStyles.length > 0 ) { + if ( imageStyles && imageStyles.length > 0 ) { // Sort styles to have "None" and "Auto" first setStyles( [ diff --git a/projects/js-packages/ai-client/src/logo-generator/hooks/use-logo-generator.ts b/projects/js-packages/ai-client/src/logo-generator/hooks/use-logo-generator.ts index cd96cb7a1610d..70acbf3fe98e0 100644 --- a/projects/js-packages/ai-client/src/logo-generator/hooks/use-logo-generator.ts +++ b/projects/js-packages/ai-client/src/logo-generator/hooks/use-logo-generator.ts @@ -92,7 +92,7 @@ const useLogoGenerator = () => { const logoGeneratorControl = aiAssistantFeatureData?.featuresControl?.[ 'logo-generator' ] as LogoGeneratorFeatureControl; - const imageStyles: Array< ImageStyleObject > = logoGeneratorControl?.styles; + const imageStyles: Array< ImageStyleObject > = logoGeneratorControl?.styles || []; const generateFirstPrompt = useCallback( async function (): Promise< string > { diff --git a/projects/js-packages/ai-client/src/logo-generator/store/actions.ts b/projects/js-packages/ai-client/src/logo-generator/store/actions.ts index 4164e5e3ca6f6..497ab74246fc9 100644 --- a/projects/js-packages/ai-client/src/logo-generator/store/actions.ts +++ b/projects/js-packages/ai-client/src/logo-generator/store/actions.ts @@ -93,6 +93,10 @@ const actions = { query: 'force=wpcom', } ); + if ( response.data ) { + throw new Error( 'Failed to fetch' ); + } + // Store the feature in the store. dispatch( actions.storeAiAssistantFeature( mapAiFeatureResponseToAiFeatureProps( response ) ) diff --git a/projects/js-packages/ai-client/src/logo-generator/store/reducer.ts b/projects/js-packages/ai-client/src/logo-generator/store/reducer.ts index a2cd92c6916f8..9322c3c21a0b4 100644 --- a/projects/js-packages/ai-client/src/logo-generator/store/reducer.ts +++ b/projects/js-packages/ai-client/src/logo-generator/store/reducer.ts @@ -325,6 +325,16 @@ export default function reducer( case ACTION_SET_FEATURE_FETCH_ERROR: return { ...state, + features: { + ...state.features, + aiAssistantFeature: { + ...state?.features?.aiAssistantFeature, + _meta: { + ...state?.features?.aiAssistantFeature?._meta, + isRequesting: false, + }, + }, + }, _meta: { ...( state._meta ?? {} ), featureFetchError: action.error, diff --git a/projects/js-packages/ai-client/src/logo-generator/store/types.ts b/projects/js-packages/ai-client/src/logo-generator/store/types.ts index 5f45e6644844c..b34f3b9f8a22e 100644 --- a/projects/js-packages/ai-client/src/logo-generator/store/types.ts +++ b/projects/js-packages/ai-client/src/logo-generator/store/types.ts @@ -220,6 +220,7 @@ export type AiAssistantFeatureEndpointResponseProps = { }; }; 'features-control'?: FeaturesControl; + data?: string; // when WP responds with a 200 status code but it's the error wrap }; export type SaveLogo = ( logo: Logo ) => Promise< { mediaId: number; mediaURL: string } >; diff --git a/projects/js-packages/ai-client/src/logo-generator/types.ts b/projects/js-packages/ai-client/src/logo-generator/types.ts index f25e238a9737c..e54cf774ac98e 100644 --- a/projects/js-packages/ai-client/src/logo-generator/types.ts +++ b/projects/js-packages/ai-client/src/logo-generator/types.ts @@ -16,7 +16,7 @@ export interface GeneratorModalProps { isOpen: boolean; onClose: () => void; onApplyLogo: ( mediaId: number ) => void; - onReload: () => void; + onReload?: () => void; context: string; placement: string; } diff --git a/projects/js-packages/components/components/threats-data-view/constants.ts b/projects/js-packages/components/components/threats-data-view/constants.ts index e9b2fea3e1db5..a3b8f4449f885 100644 --- a/projects/js-packages/components/components/threats-data-view/constants.ts +++ b/projects/js-packages/components/components/threats-data-view/constants.ts @@ -2,11 +2,12 @@ import { __ } from '@wordpress/i18n'; export const PAID_PLUGIN_SUPPORT_URL = 'https://jetpack.com/contact-support/?rel=support'; -export const THREAT_STATUSES = [ - { value: 'current', label: __( 'Active', 'jetpack' ) }, - { value: 'fixed', label: __( 'Fixed', 'jetpack' ) }, - { value: 'ignored', label: __( 'Ignored', 'jetpack' ) }, -]; +export const THREAT_STATUSES: { value: string; label: string; variant?: 'success' | 'warning' }[] = + [ + { value: 'current', label: __( 'Active', 'jetpack' ), variant: 'warning' }, + { value: 'fixed', label: __( 'Fixed', 'jetpack' ), variant: 'success' }, + { value: 'ignored', label: __( 'Ignored', 'jetpack' ) }, + ]; export const THREAT_TYPES = [ { value: 'plugin', label: __( 'Plugin', 'jetpack' ) }, diff --git a/projects/js-packages/components/components/threats-data-view/fixer-status.tsx b/projects/js-packages/components/components/threats-data-view/fixer-status.tsx index 89c68bc56b4cf..ede662ab10b82 100644 --- a/projects/js-packages/components/components/threats-data-view/fixer-status.tsx +++ b/projects/js-packages/components/components/threats-data-view/fixer-status.tsx @@ -55,7 +55,7 @@ export default function FixerStatusIcon( { contact support.', diff --git a/projects/js-packages/components/components/threats-data-view/index.tsx b/projects/js-packages/components/components/threats-data-view/index.tsx index d02d077e626be..637618ec6762e 100644 --- a/projects/js-packages/components/components/threats-data-view/index.tsx +++ b/projects/js-packages/components/components/threats-data-view/index.tsx @@ -1,15 +1,17 @@ -import { Icon } from '@wordpress/components'; import { Action, DataViews, Field, + FieldType, Filter, filterSortAndPaginate, SortDirection, SupportedLayouts, type View, } from '@wordpress/dataviews'; +import { dateI18n } from '@wordpress/date'; import { __, _x } from '@wordpress/i18n'; +import { Icon } from '@wordpress/icons'; import { useCallback, useMemo, useState } from 'react'; import Badge from '../badge'; import { THREAT_STATUSES, THREAT_TYPES } from './constants'; @@ -62,7 +64,7 @@ export default function ThreatsDataView( { search: '', filters: filters || [], page: 1, - perPage: 25, + perPage: 20, }; /** @@ -209,6 +211,15 @@ export default function ThreatsDataView( { THREAT_STATUSES.find( ( { value } ) => value === item.status )?.value ?? item.status ); }, + render( { item }: { item: DataViewThreat } ) { + if ( item.status ) { + const status = THREAT_STATUSES.find( ( { value } ) => value === item.status ); + if ( status ) { + return { status?.label }; + } + } + return { __( 'Active', 'jetpack' ) }; + }, }, { id: 'extension', @@ -322,6 +333,44 @@ export default function ThreatsDataView( { }, ] : [] ), + ...( dataFields.includes( 'firstDetected' ) + ? [ + { + id: 'first-detected', + label: __( 'First Detected', 'jetpack' ), + type: 'datetime' as FieldType, + getValue( { item }: { item: DataViewThreat } ) { + return new Date( item.firstDetected ); + }, + render( { item }: { item: DataViewThreat } ) { + return ( + + { dateI18n( 'F j Y', item.firstDetected, false ) } + + ); + }, + }, + ] + : [] ), + ...( dataFields.includes( 'fixedOn' ) + ? [ + { + id: 'fixed-on', + label: __( 'Fixed On', 'jetpack' ), + type: 'datetime' as FieldType, + getValue( { item }: { item: DataViewThreat } ) { + return new Date( item.firstDetected ); + }, + render( { item }: { item: DataViewThreat } ) { + return ( + + { dateI18n( 'F j Y', item.firstDetected, false ) } + + ); + }, + }, + ] + : [] ), ]; return result; diff --git a/projects/js-packages/components/components/threats-data-view/stories/index.stories.tsx b/projects/js-packages/components/components/threats-data-view/stories/index.stories.tsx index 676debe4cf6c8..ef738f23f8e98 100644 --- a/projects/js-packages/components/components/threats-data-view/stories/index.stories.tsx +++ b/projects/js-packages/components/components/threats-data-view/stories/index.stories.tsx @@ -32,7 +32,7 @@ Default.args = { fixedOn: null, severity: 8, fixable: { fixer: 'rollback', target: 'January 26, 2024, 6:49 am', extensionStatus: '' }, - fixer: { status: 'in_progress', last_updated: new Date().toISOString() }, + fixer: { status: 'not_started' }, status: 'current', filename: '/var/www/html/wp-content/index.php', context: { @@ -94,6 +94,7 @@ Default.args = { fixedOn: null, severity: 3, fixable: { fixer: 'update', target: '1.12.4', extensionStatus: 'inactive' }, + fixer: { status: 'in_progress', last_updated: new Date().toISOString() }, status: 'current', filename: null, context: null, diff --git a/projects/js-packages/components/components/threats-data-view/styles.module.scss b/projects/js-packages/components/components/threats-data-view/styles.module.scss index 31b652ea8eacb..32831f1094814 100644 --- a/projects/js-packages/components/components/threats-data-view/styles.module.scss +++ b/projects/js-packages/components/components/threats-data-view/styles.module.scss @@ -17,7 +17,7 @@ .dataviews-view-list .dataviews-views-list__fields { align-items: center; } - + .dataviews-view-table th.dataviews-view-table__actions-column { text-align: left; } @@ -130,27 +130,13 @@ font-size: 12px; } -.icon-spinner { - svg { - margin: 0; - } -} - -.spinner-spacer { - margin-left: 8px; +.threat__fixedOn, +.threat__firstDetected { + white-space: nowrap; } -.info-spacer { - margin-left: 4px; -} - -.check-spacer { - margin-left: -2px; -} - -.threat__fixer { - min-width: 54px; - text-align: center; +.threat__fixedOn { + color: var( --jp-green-70 ); } .threat__action { @@ -173,4 +159,4 @@ border: 1px solid var( --jp-highlight ); } } -} \ No newline at end of file +} diff --git a/projects/js-packages/publicize-components/changelog/fix-social-bluesky-reconnection-for-broken-connections b/projects/js-packages/publicize-components/changelog/fix-social-bluesky-reconnection-for-broken-connections new file mode 100644 index 0000000000000..eb4d17f671962 --- /dev/null +++ b/projects/js-packages/publicize-components/changelog/fix-social-bluesky-reconnection-for-broken-connections @@ -0,0 +1,4 @@ +Significance: patch +Type: fixed + +Fixed reconnection for broken Bluesky connections diff --git a/projects/js-packages/publicize-components/changelog/update-enhances-publishing-feature-check b/projects/js-packages/publicize-components/changelog/update-enhances-publishing-feature-check new file mode 100644 index 0000000000000..e1af3f96c5a7e --- /dev/null +++ b/projects/js-packages/publicize-components/changelog/update-enhances-publishing-feature-check @@ -0,0 +1,4 @@ +Significance: patch +Type: changed + +Initial state: Migrated isEnhancedPublishingEnabled to feature check diff --git a/projects/js-packages/publicize-components/src/components/connection-management/reconnect.tsx b/projects/js-packages/publicize-components/src/components/connection-management/reconnect.tsx index 107fdc5240c10..d6e11e80cf36e 100644 --- a/projects/js-packages/publicize-components/src/components/connection-management/reconnect.tsx +++ b/projects/js-packages/publicize-components/src/components/connection-management/reconnect.tsx @@ -58,11 +58,7 @@ export function Reconnect( { connection, service, variant = 'link' }: ReconnectP return; } - await setReconnectingAccount( - // Join service name and external ID - // just in case the external ID alone is not unique. - `${ connection.service_name }:${ connection.external_id }` - ); + await setReconnectingAccount( connection ); const formData = new FormData(); @@ -70,8 +66,19 @@ export function Reconnect( { connection, service, variant = 'link' }: ReconnectP formData.set( 'instance', connection.external_display ); } - requestAccess( formData ); - }, [ connection, deleteConnectionById, requestAccess, service.ID, setReconnectingAccount ] ); + if ( service.ID === 'bluesky' ) { + openConnectionsModal(); + } else { + requestAccess( formData ); + } + }, [ + connection, + deleteConnectionById, + openConnectionsModal, + requestAccess, + service.ID, + setReconnectingAccount, + ] ); if ( ! connection.can_disconnect ) { return null; diff --git a/projects/js-packages/publicize-components/src/components/form/instagram-no-media-notice.tsx b/projects/js-packages/publicize-components/src/components/form/instagram-no-media-notice.tsx index 2adeb6ceb74b8..87363f4f46077 100644 --- a/projects/js-packages/publicize-components/src/components/form/instagram-no-media-notice.tsx +++ b/projects/js-packages/publicize-components/src/components/form/instagram-no-media-notice.tsx @@ -1,13 +1,12 @@ import { getRedirectUrl } from '@automattic/jetpack-components'; +import { siteHasFeature } from '@automattic/jetpack-script-data'; import { ExternalLink } from '@wordpress/components'; import { __ } from '@wordpress/i18n'; -import { usePublicizeConfig } from '../../..'; +import { features } from '../../utils/constants'; import Notice from '../notice'; export const InstagramNoMediaNotice: React.FC = () => { - const { isEnhancedPublishingEnabled } = usePublicizeConfig(); - - return isEnhancedPublishingEnabled ? ( + return siteHasFeature( features.ENHANCED_PUBLISHING ) ? ( { __( 'To share to Instagram, add an image/video, or enable Social Image Generator.', diff --git a/projects/js-packages/publicize-components/src/components/form/share-post-form.tsx b/projects/js-packages/publicize-components/src/components/form/share-post-form.tsx index 92794ff64f661..11ecd5e45aa23 100644 --- a/projects/js-packages/publicize-components/src/components/form/share-post-form.tsx +++ b/projects/js-packages/publicize-components/src/components/form/share-post-form.tsx @@ -1,5 +1,6 @@ -import { usePublicizeConfig } from '../../..'; +import { siteHasFeature } from '@automattic/jetpack-script-data'; import useSocialMediaMessage from '../../hooks/use-social-media-message'; +import { features } from '../../utils/constants'; import MediaSection from '../media-section'; import MessageBoxControl from '../message-box-control'; @@ -16,8 +17,6 @@ type SharePostFormProps = { export const SharePostForm: React.FC< SharePostFormProps > = ( { analyticsData = null } ) => { const { message, updateMessage, maxLength } = useSocialMediaMessage(); - const { isEnhancedPublishingEnabled } = usePublicizeConfig(); - return ( <> = ( { analyticsData = message={ message } analyticsData={ analyticsData } /> - { isEnhancedPublishingEnabled && } + { siteHasFeature( features.ENHANCED_PUBLISHING ) && ( + + ) } ); }; diff --git a/projects/js-packages/publicize-components/src/components/manage-connections-modal/confirmation-form/index.tsx b/projects/js-packages/publicize-components/src/components/manage-connections-modal/confirmation-form/index.tsx index 4eecc6d050a37..6ffc93c8ca59b 100644 --- a/projects/js-packages/publicize-components/src/components/manage-connections-modal/confirmation-form/index.tsx +++ b/projects/js-packages/publicize-components/src/components/manage-connections-modal/confirmation-form/index.tsx @@ -90,7 +90,7 @@ export function ConfirmationForm( { keyringResult, onComplete, isAdmin }: Confir // If user account is supported, add it to the list if ( ! service.external_users_only ) { options.push( { - label: keyringResult.external_display, + label: keyringResult.external_display || keyringResult.external_name, value: keyringResult.external_ID, profile_picture: keyringResult.external_profile_picture, } ); @@ -150,7 +150,7 @@ export function ConfirmationForm( { keyringResult, onComplete, isAdmin }: Confir ); if ( reconnectingAccount ) { - setReconnectingAccount( '' ); + setReconnectingAccount( undefined ); } // Do not await the connection creation to unblock the UI @@ -215,7 +215,8 @@ export function ConfirmationForm( { keyringResult, onComplete, isAdmin }: Confir // If we are reconnecting an account, preselect it, // otherwise, preselect the first account const defaultChecked = reconnectingAccount - ? reconnectingAccount === `${ service?.ID }:${ option.value }` + ? reconnectingAccount.service_name === service?.ID && + reconnectingAccount.external_id === option.value : index === 0; return ( diff --git a/projects/js-packages/publicize-components/src/components/manage-connections-modal/index.tsx b/projects/js-packages/publicize-components/src/components/manage-connections-modal/index.tsx index 129dcbc54d9ba..336597e2dcaf2 100644 --- a/projects/js-packages/publicize-components/src/components/manage-connections-modal/index.tsx +++ b/projects/js-packages/publicize-components/src/components/manage-connections-modal/index.tsx @@ -24,14 +24,15 @@ export const ManageConnectionsModal = () => { }; }, [] ); - const { setKeyringResult, closeConnectionsModal } = useDispatch( store ); + const { setKeyringResult, closeConnectionsModal, setReconnectingAccount } = useDispatch( store ); const [ isSmall ] = useBreakpointMatch( 'sm' ); const closeModal = useCallback( () => { setKeyringResult( null ); + setReconnectingAccount( undefined ); closeConnectionsModal(); - }, [ closeConnectionsModal, setKeyringResult ] ); + }, [ closeConnectionsModal, setKeyringResult, setReconnectingAccount ] ); const hasKeyringResult = Boolean( keyringResult?.ID ); diff --git a/projects/js-packages/publicize-components/src/components/services/custom-inputs.tsx b/projects/js-packages/publicize-components/src/components/services/custom-inputs.tsx index 4064facfbf9ed..95e02ed8c8729 100644 --- a/projects/js-packages/publicize-components/src/components/services/custom-inputs.tsx +++ b/projects/js-packages/publicize-components/src/components/services/custom-inputs.tsx @@ -1,6 +1,9 @@ +import { Alert } from '@automattic/jetpack-components'; import { ExternalLink } from '@wordpress/components'; +import { useSelect } from '@wordpress/data'; import { createInterpolateElement, useId } from '@wordpress/element'; import { __, _x } from '@wordpress/i18n'; +import { store } from '../../social-store'; import { SupportedService } from '../services/use-supported-services'; import styles from './style.module.scss'; @@ -17,6 +20,8 @@ type CustomInputsProps = { export function CustomInputs( { service }: CustomInputsProps ) { const id = useId(); + const reconnectingAccount = useSelect( select => select( store ).getReconnectingAccount(), [] ); + if ( 'mastodon' === service.ID ) { return (
@@ -58,6 +63,11 @@ export function CustomInputs( { service }: CustomInputsProps ) { required type="text" name="handle" + defaultValue={ + reconnectingAccount?.service_name === 'bluesky' + ? reconnectingAccount?.external_name + : undefined + } autoComplete="off" autoCapitalize="off" autoCorrect="off" @@ -93,6 +103,11 @@ export function CustomInputs( { service }: CustomInputsProps ) { aria-describedby={ `${ id }-password-description` } placeholder={ 'xxxx-xxxx-xxxx-xxxx' } /> + { reconnectingAccount?.service_name === 'bluesky' && ( + + { __( 'Please provide an app password to fix the connection.', 'jetpack' ) } + + ) }
); diff --git a/projects/js-packages/publicize-components/src/components/services/service-item.tsx b/projects/js-packages/publicize-components/src/components/services/service-item.tsx index 2020e883690a1..00754aa1a1e38 100644 --- a/projects/js-packages/publicize-components/src/components/services/service-item.tsx +++ b/projects/js-packages/publicize-components/src/components/services/service-item.tsx @@ -1,6 +1,6 @@ import { Button, useBreakpointMatch } from '@automattic/jetpack-components'; import { Panel, PanelBody } from '@wordpress/components'; -import { useReducer } from '@wordpress/element'; +import { useEffect, useReducer, useRef } from '@wordpress/element'; import { __, _x } from '@wordpress/i18n'; import { Icon, chevronDown, chevronUp } from '@wordpress/icons'; import { ConnectForm } from './connect-form'; @@ -8,7 +8,9 @@ import { ServiceItemDetails, ServicesItemDetailsProps } from './service-item-det import { ServiceStatus } from './service-status'; import styles from './style.module.scss'; -export type ServicesItemProps = ServicesItemDetailsProps; +export type ServicesItemProps = ServicesItemDetailsProps & { + isPanelDefaultOpen?: boolean; +}; /** * Service item component @@ -17,10 +19,22 @@ export type ServicesItemProps = ServicesItemDetailsProps; * * @return {import('react').ReactNode} Service item component */ -export function ServiceItem( { service, serviceConnections }: ServicesItemProps ) { +export function ServiceItem( { + service, + serviceConnections, + isPanelDefaultOpen, +}: ServicesItemProps ) { const [ isSmall ] = useBreakpointMatch( 'sm' ); - const [ isPanelOpen, togglePanel ] = useReducer( state => ! state, false ); + const [ isPanelOpen, togglePanel ] = useReducer( state => ! state, isPanelDefaultOpen ); + const panelRef = useRef< HTMLDivElement >( null ); + + useEffect( () => { + if ( isPanelDefaultOpen ) { + panelRef.current?.scrollIntoView( { block: 'center', behavior: 'smooth' } ); + } + // eslint-disable-next-line react-hooks/exhaustive-deps + }, [] ); const areCustomInputsVisible = isPanelOpen && service.needsCustomInputs; @@ -94,7 +108,7 @@ export function ServiceItem( { service, serviceConnections }: ServicesItemProps - + { diff --git a/projects/js-packages/publicize-components/src/components/services/services-list.tsx b/projects/js-packages/publicize-components/src/components/services/services-list.tsx index c2cdf4c4ac8b9..1a5c030c07820 100644 --- a/projects/js-packages/publicize-components/src/components/services/services-list.tsx +++ b/projects/js-packages/publicize-components/src/components/services/services-list.tsx @@ -27,11 +27,17 @@ export function ServicesList() { }, {} ); }, [] ); + const reconnectingAccount = useSelect( select => select( store ).getReconnectingAccount(), [] ); + return (
    { supportedServices.map( service => (
  • - +
  • ) ) }
diff --git a/projects/js-packages/publicize-components/src/components/services/use-request-access.ts b/projects/js-packages/publicize-components/src/components/services/use-request-access.ts index 18afab50c92d2..e12af39dfefca 100644 --- a/projects/js-packages/publicize-components/src/components/services/use-request-access.ts +++ b/projects/js-packages/publicize-components/src/components/services/use-request-access.ts @@ -96,7 +96,10 @@ export function useRequestAccess( { service, onConfirm }: RequestAccessOptions ) } url.searchParams.set( 'handle', handle ); - url.searchParams.set( 'app_password', formData.get( 'app_password' ).toString().trim() ); + url.searchParams.set( + 'app_password', + ( formData.get( 'app_password' )?.toString() || '' ).trim() + ); break; } diff --git a/projects/js-packages/publicize-components/src/components/social-previews/instagram.js b/projects/js-packages/publicize-components/src/components/social-previews/instagram.js index 8af81b876c12e..96178d1b6b7c6 100644 --- a/projects/js-packages/publicize-components/src/components/social-previews/instagram.js +++ b/projects/js-packages/publicize-components/src/components/social-previews/instagram.js @@ -1,12 +1,13 @@ import { Notice, getRedirectUrl } from '@automattic/jetpack-components'; +import { siteHasFeature } from '@automattic/jetpack-script-data'; import { InstagramPreviews } from '@automattic/social-previews'; import { ExternalLink } from '@wordpress/components'; import { useSelect } from '@wordpress/data'; import { __, _x } from '@wordpress/i18n'; import React from 'react'; -import usePublicizeConfig from '../../hooks/use-publicize-config'; import useSocialMediaMessage from '../../hooks/use-social-media-message'; import { SOCIAL_STORE_ID, CONNECTION_SERVICE_INSTAGRAM_BUSINESS } from '../../social-store'; +import { features } from '../../utils/constants'; /** * The Instagram tab component. @@ -19,7 +20,6 @@ export function Instagram( props ) { const { username: name, profileImage } = useSelect( select => select( SOCIAL_STORE_ID ).getConnectionProfileDetails( CONNECTION_SERVICE_INSTAGRAM_BUSINESS ) ); - const { isEnhancedPublishingEnabled } = usePublicizeConfig(); const { message: text } = useSocialMediaMessage(); @@ -42,7 +42,7 @@ export function Instagram( props ) { , ] } > - { isEnhancedPublishingEnabled + { siteHasFeature( features.ENHANCED_PUBLISHING ) ? __( 'To share to Instagram, add an image/video, or enable Social Image Generator.', 'jetpack' diff --git a/projects/js-packages/publicize-components/src/hooks/use-publicize-config/index.js b/projects/js-packages/publicize-components/src/hooks/use-publicize-config/index.js index 0b093fb1100a1..bb991a44dd85e 100644 --- a/projects/js-packages/publicize-components/src/hooks/use-publicize-config/index.js +++ b/projects/js-packages/publicize-components/src/hooks/use-publicize-config/index.js @@ -86,13 +86,6 @@ export default function usePublicizeConfig() { */ const hasPaidPlan = !! getJetpackData()?.social?.hasPaidPlan; - /** - * isEnhancedPublishingEnabled: - * Whether the site has the enhanced publishing feature enabled. If true, it means that - * the site has the Advanced plan. - */ - const isEnhancedPublishingEnabled = !! getJetpackData()?.social?.isEnhancedPublishingEnabled; - /**\ * Returns true if the post type is a Jetpack Social Note. */ @@ -110,7 +103,6 @@ export default function usePublicizeConfig() { hidePublicizeFeature, isPostAlreadyShared, hasPaidPlan, - isEnhancedPublishingEnabled, isSocialImageGeneratorAvailable: !! getJetpackData()?.social?.isSocialImageGeneratorAvailable && ! isJetpackSocialNote, isSocialImageGeneratorEnabled: !! getJetpackData()?.social?.isSocialImageGeneratorEnabled, diff --git a/projects/js-packages/publicize-components/src/social-store/actions/connection-data.js b/projects/js-packages/publicize-components/src/social-store/actions/connection-data.js index 8c23c207ad21d..78012e39b3db5 100644 --- a/projects/js-packages/publicize-components/src/social-store/actions/connection-data.js +++ b/projects/js-packages/publicize-components/src/social-store/actions/connection-data.js @@ -441,7 +441,7 @@ export function updatingConnection( connectionId, updating = true ) { /** * Sets the reconnecting account. * - * @param {string} reconnectingAccount - Account being reconnected. + * @param {import('../types').Connection} reconnectingAccount - Account being reconnected. * * @return {object} Reconnecting account action. */ diff --git a/projects/js-packages/publicize-components/src/social-store/selectors/connection-data.js b/projects/js-packages/publicize-components/src/social-store/selectors/connection-data.js index 1a324a65d3cd7..25b675d301c4d 100644 --- a/projects/js-packages/publicize-components/src/social-store/selectors/connection-data.js +++ b/projects/js-packages/publicize-components/src/social-store/selectors/connection-data.js @@ -181,7 +181,7 @@ export function getUpdatingConnections( state ) { * @return {import("../types").ConnectionData['reconnectingAccount']} The account being reconnected. */ export function getReconnectingAccount( state ) { - return state.connectionData?.reconnectingAccount ?? ''; + return state.connectionData?.reconnectingAccount; } /** diff --git a/projects/js-packages/publicize-components/src/social-store/selectors/jetpack-settings.js b/projects/js-packages/publicize-components/src/social-store/selectors/jetpack-settings.js index 66fd71d5add49..1eb9be3e6e729 100644 --- a/projects/js-packages/publicize-components/src/social-store/selectors/jetpack-settings.js +++ b/projects/js-packages/publicize-components/src/social-store/selectors/jetpack-settings.js @@ -4,7 +4,6 @@ const jetpackSettingSelectors = { showPricingPage: state => state.jetpackSettings.show_pricing_page, isUpdatingJetpackSettings: state => state.jetpackSettings.is_updating, hasPaidPlan: state => ! ( state.jetpackSettings?.showNudge ?? true ), - isEnhancedPublishingEnabled: state => state.jetpackSettings?.isEnhancedPublishingEnabled ?? false, getDismissedNotices: state => state.jetpackSettings?.dismissedNotices, isSocialNotesEnabled: state => state.jetpackSettings?.social_notes_enabled, isSocialNotesSettingsUpdating: state => state.jetpackSettings?.social_notes_is_updating, diff --git a/projects/js-packages/publicize-components/src/social-store/types.ts b/projects/js-packages/publicize-components/src/social-store/types.ts index a391f53024082..afe11754eb291 100644 --- a/projects/js-packages/publicize-components/src/social-store/types.ts +++ b/projects/js-packages/publicize-components/src/social-store/types.ts @@ -25,7 +25,7 @@ export type ConnectionData = { connections: Connection[]; deletingConnections?: Array< number | string >; updatingConnections?: Array< number | string >; - reconnectingAccount?: string; + reconnectingAccount?: Connection; keyringResult?: KeyringResult; }; diff --git a/projects/js-packages/publicize-components/src/utils/constants.ts b/projects/js-packages/publicize-components/src/utils/constants.ts new file mode 100644 index 0000000000000..9ac40038d75b8 --- /dev/null +++ b/projects/js-packages/publicize-components/src/utils/constants.ts @@ -0,0 +1,3 @@ +export const features = { + ENHANCED_PUBLISHING: 'social-enhanced-publishing', +}; diff --git a/projects/packages/publicize/changelog/fix-social-bsky-profile-url b/projects/packages/publicize/changelog/fix-social-bsky-profile-url new file mode 100644 index 0000000000000..ebe3332ec44de --- /dev/null +++ b/projects/packages/publicize/changelog/fix-social-bsky-profile-url @@ -0,0 +1,4 @@ +Significance: minor +Type: fixed + +Social: Fix Bsky profile URL diff --git a/projects/packages/publicize/src/class-publicize-base.php b/projects/packages/publicize/src/class-publicize-base.php index 5e5964fb64afb..b88bd1a6b12ca 100644 --- a/projects/packages/publicize/src/class-publicize-base.php +++ b/projects/packages/publicize/src/class-publicize-base.php @@ -517,6 +517,10 @@ public function get_profile_link( $service_name, $connection ) { return 'https://twitter.com/' . substr( $cmeta['external_display'], 1 ); // Has a leading '@'. } + if ( 'bluesky' === $service_name ) { + return 'https://bsky.app/profile/' . $cmeta['external_id']; + } + if ( 'linkedin' === $service_name ) { if ( ! isset( $cmeta['connection_data']['meta']['profile_url'] ) ) { return false; diff --git a/projects/packages/sync/changelog/revert-39658-update-jetpack-sync-whitelist b/projects/packages/sync/changelog/revert-39658-update-jetpack-sync-whitelist new file mode 100644 index 0000000000000..59df2569689e4 --- /dev/null +++ b/projects/packages/sync/changelog/revert-39658-update-jetpack-sync-whitelist @@ -0,0 +1,5 @@ +Significance: patch +Type: removed +Comment: Revert "Jetpack Sync: Add 'woocommerce_analytics_first_activation' in options' whitelist" + + diff --git a/projects/packages/sync/src/class-defaults.php b/projects/packages/sync/src/class-defaults.php index 3896ee4d9cdf9..612b077e4f970 100644 --- a/projects/packages/sync/src/class-defaults.php +++ b/projects/packages/sync/src/class-defaults.php @@ -213,7 +213,6 @@ class Defaults { 'jetpack_waf_share_data', 'jetpack_waf_share_debug_data', 'jetpack_waf_automatic_rules_last_updated_timestamp', - 'woocommerce_analytics_first_activation', ); /** diff --git a/projects/plugins/boost/app/lib/critical-css/source-providers/providers/WP_Core_Provider.php b/projects/plugins/boost/app/lib/critical-css/source-providers/providers/WP_Core_Provider.php index e2b63769a6784..68445b4031fbb 100644 --- a/projects/plugins/boost/app/lib/critical-css/source-providers/providers/WP_Core_Provider.php +++ b/projects/plugins/boost/app/lib/critical-css/source-providers/providers/WP_Core_Provider.php @@ -43,8 +43,8 @@ public static function get_critical_source_urls( $context_posts = array() ) { if ( ! empty( $permalink ) ) { $urls['posts_page'] = array( $permalink ); } - } else { - $urls['posts_page'] = (array) home_url( '/' ); + } elseif ( ! $front_page ) { + $urls['posts_page'] = array( home_url( '/' ) ); } return $urls; diff --git a/projects/plugins/boost/changelog/update-ccss-core-providers b/projects/plugins/boost/changelog/update-ccss-core-providers new file mode 100644 index 0000000000000..527e9511c0c8b --- /dev/null +++ b/projects/plugins/boost/changelog/update-ccss-core-providers @@ -0,0 +1,4 @@ +Significance: patch +Type: changed + +Critical CSS: Make the list of critical CSS URLs more efficient. diff --git a/projects/plugins/jetpack/_inc/client/newsletter/subscriptions-settings.jsx b/projects/plugins/jetpack/_inc/client/newsletter/subscriptions-settings.jsx index 6f12121a00c07..984e585d74163 100644 --- a/projects/plugins/jetpack/_inc/client/newsletter/subscriptions-settings.jsx +++ b/projects/plugins/jetpack/_inc/client/newsletter/subscriptions-settings.jsx @@ -38,6 +38,7 @@ function SubscriptionsSettings( props ) { isStcEnabled, isSmEnabled, isSubscribeOverlayEnabled, + isSubscribeFloatingEnabled, isSubscribePostEndEnabled, isLoginNavigationEnabled, isSubscribeNavigationEnabled, @@ -69,6 +70,15 @@ function SubscriptionsSettings( props ) { } ) : null; + const subscribeFloatingEditorUrl = + siteAdminUrl && themeStylesheet + ? addQueryArgs( `${ siteAdminUrl }site-editor.php`, { + postType: 'wp_template_part', + postId: `${ themeStylesheet }//jetpack-subscribe-floating-button`, + canvas: 'edit', + } ) + : null; + const singlePostTemplateEditorUrl = siteAdminUrl ? addQueryArgs( `${ siteAdminUrl }site-editor.php`, { postType: 'wp_template', @@ -99,6 +109,13 @@ function SubscriptionsSettings( props ) { updateFormStateModuleOption( SUBSCRIPTIONS_MODULE_NAME, 'jetpack_subscribe_overlay_enabled' ); }, [ updateFormStateModuleOption ] ); + const handleSubscribeFloatingToggleChange = useCallback( () => { + updateFormStateModuleOption( + SUBSCRIPTIONS_MODULE_NAME, + 'jetpack_subscribe_floating_button_enabled' + ); + }, [ updateFormStateModuleOption ] ); + const handleSubscribePostEndToggleChange = useCallback( () => { updateFormStateModuleOption( SUBSCRIPTIONS_MODULE_NAME, @@ -202,6 +219,25 @@ function SubscriptionsSettings( props ) { } /> + + { __( "Floating subscribe button on site's bottom corner", 'jetpack' ) } + { isBlockTheme && subscribeFloatingEditorUrl && ( + <> + { '. ' } + + { __( 'Preview and edit', 'jetpack' ) } + + + ) } + + } + /> { isSubscriptionSiteEditSupported && ( @@ -293,6 +329,9 @@ export default withModuleSettingsFormHelpers( isStcEnabled: ownProps.getOptionValue( 'stc_enabled' ), isSmEnabled: ownProps.getOptionValue( 'sm_enabled' ), isSubscribeOverlayEnabled: ownProps.getOptionValue( 'jetpack_subscribe_overlay_enabled' ), + isSubscribeFloatingEnabled: ownProps.getOptionValue( + 'jetpack_subscribe_floating_button_enabled' + ), isSubscribePostEndEnabled: ownProps.getOptionValue( 'jetpack_subscriptions_subscribe_post_end_enabled' ), diff --git a/projects/plugins/jetpack/_inc/lib/class.core-rest-api-endpoints.php b/projects/plugins/jetpack/_inc/lib/class.core-rest-api-endpoints.php index 8122e2ad76477..e56d427c0c5ea 100644 --- a/projects/plugins/jetpack/_inc/lib/class.core-rest-api-endpoints.php +++ b/projects/plugins/jetpack/_inc/lib/class.core-rest-api-endpoints.php @@ -2256,7 +2256,7 @@ public static function get_updateable_data_list( $selector = '' ) { $options = array( // Blocks. - 'jetpack_blocks_disabled' => array( + 'jetpack_blocks_disabled' => array( 'description' => esc_html__( 'Jetpack Blocks disabled.', 'jetpack' ), 'type' => 'boolean', 'default' => false, @@ -2265,7 +2265,7 @@ public static function get_updateable_data_list( $selector = '' ) { ), // Carousel - 'carousel_background_color' => array( + 'carousel_background_color' => array( 'description' => esc_html__( 'Color scheme.', 'jetpack' ), 'type' => 'string', 'default' => 'black', @@ -2280,7 +2280,7 @@ public static function get_updateable_data_list( $selector = '' ) { 'validate_callback' => __CLASS__ . '::validate_list_item', 'jp_group' => 'carousel', ), - 'carousel_display_exif' => array( + 'carousel_display_exif' => array( 'description' => wp_kses( sprintf( __( 'Show photo metadata (Exif) in carousel, when available.', 'jetpack' ) ), array( @@ -2295,7 +2295,7 @@ public static function get_updateable_data_list( $selector = '' ) { 'validate_callback' => __CLASS__ . '::validate_boolean', 'jp_group' => 'carousel', ), - 'carousel_display_comments' => array( + 'carousel_display_comments' => array( 'description' => esc_html__( 'Show comments area in carousel', 'jetpack' ), 'type' => 'boolean', 'default' => 1, @@ -2304,14 +2304,14 @@ public static function get_updateable_data_list( $selector = '' ) { ), // Comments. - 'highlander_comment_form_prompt' => array( + 'highlander_comment_form_prompt' => array( 'description' => esc_html__( 'Greeting Text', 'jetpack' ), 'type' => 'string', 'default' => esc_html__( 'Leave a Reply', 'jetpack' ), 'sanitize_callback' => 'sanitize_text_field', 'jp_group' => 'comments', ), - 'jetpack_comment_form_color_scheme' => array( + 'jetpack_comment_form_color_scheme' => array( 'description' => esc_html__( 'Color scheme', 'jetpack' ), 'type' => 'string', 'default' => 'light', @@ -2330,28 +2330,28 @@ public static function get_updateable_data_list( $selector = '' ) { ), // Custom Content Types. - 'jetpack_portfolio' => array( + 'jetpack_portfolio' => array( 'description' => esc_html__( 'Enable or disable Jetpack portfolio post type.', 'jetpack' ), 'type' => 'boolean', 'default' => 0, 'validate_callback' => __CLASS__ . '::validate_boolean', 'jp_group' => 'custom-content-types', ), - 'jetpack_portfolio_posts_per_page' => array( + 'jetpack_portfolio_posts_per_page' => array( 'description' => esc_html__( 'Number of entries to show at most in Portfolio pages.', 'jetpack' ), 'type' => 'integer', 'default' => 10, 'validate_callback' => __CLASS__ . '::validate_posint', 'jp_group' => 'custom-content-types', ), - 'jetpack_testimonial' => array( + 'jetpack_testimonial' => array( 'description' => esc_html__( 'Enable or disable Jetpack testimonial post type.', 'jetpack' ), 'type' => 'boolean', 'default' => 0, 'validate_callback' => __CLASS__ . '::validate_boolean', 'jp_group' => 'custom-content-types', ), - 'jetpack_testimonial_posts_per_page' => array( + 'jetpack_testimonial_posts_per_page' => array( 'description' => esc_html__( 'Number of entries to show at most in Testimonial pages.', 'jetpack' ), 'type' => 'integer', 'default' => 10, @@ -2360,21 +2360,21 @@ public static function get_updateable_data_list( $selector = '' ) { ), // WAF. - 'jetpack_waf_automatic_rules' => array( + 'jetpack_waf_automatic_rules' => array( 'description' => esc_html__( 'Enable automatic rules - Protect your site against untrusted traffic sources with automatic security rules.', 'jetpack' ), 'type' => 'boolean', 'default' => Waf_Compatibility::get_default_automatic_rules_option(), 'validate_callback' => __CLASS__ . '::validate_boolean', 'jp_group' => 'waf', ), - 'jetpack_waf_ip_block_list_enabled' => array( + 'jetpack_waf_ip_block_list_enabled' => array( 'description' => esc_html__( 'Block list - Block a specific request IP.', 'jetpack' ), 'type' => 'boolean', 'default' => 0, 'validate_callback' => __CLASS__ . '::validate_boolean', 'jp_group' => 'waf', ), - 'jetpack_waf_ip_block_list' => array( + 'jetpack_waf_ip_block_list' => array( 'description' => esc_html__( 'Blocked IP addresses', 'jetpack' ), 'type' => 'string', 'default' => '', @@ -2382,14 +2382,14 @@ public static function get_updateable_data_list( $selector = '' ) { 'sanitize_callback' => 'esc_textarea', 'jp_group' => 'waf', ), - 'jetpack_waf_ip_allow_list_enabled' => array( + 'jetpack_waf_ip_allow_list_enabled' => array( 'description' => esc_html__( 'Allow list - Allow a specific request IP.', 'jetpack' ), 'type' => 'boolean', 'default' => 0, 'validate_callback' => __CLASS__ . '::validate_boolean', 'jp_group' => 'settings', ), - 'jetpack_waf_ip_allow_list' => array( + 'jetpack_waf_ip_allow_list' => array( 'description' => esc_html__( 'Always allowed IP addresses', 'jetpack' ), 'type' => 'string', 'default' => '', @@ -2397,14 +2397,14 @@ public static function get_updateable_data_list( $selector = '' ) { 'sanitize_callback' => 'esc_textarea', 'jp_group' => 'settings', ), - 'jetpack_waf_share_data' => array( + 'jetpack_waf_share_data' => array( 'description' => esc_html__( 'Share basic data with Jetpack.', 'jetpack' ), 'type' => 'boolean', 'default' => 0, 'validate_callback' => __CLASS__ . '::validate_boolean', 'jp_group' => 'waf', ), - 'jetpack_waf_share_debug_data' => array( + 'jetpack_waf_share_debug_data' => array( 'description' => esc_html__( 'Share detailed data with Jetpack.', 'jetpack' ), 'type' => 'boolean', 'default' => 0, @@ -2412,7 +2412,7 @@ public static function get_updateable_data_list( $selector = '' ) { 'jp_group' => 'waf', ), // Galleries. - 'tiled_galleries' => array( + 'tiled_galleries' => array( 'description' => esc_html__( 'Display all your gallery pictures in a cool mosaic.', 'jetpack' ), 'type' => 'boolean', 'default' => 0, @@ -2420,7 +2420,7 @@ public static function get_updateable_data_list( $selector = '' ) { 'jp_group' => 'tiled-gallery', ), - 'gravatar_disable_hovercards' => array( + 'gravatar_disable_hovercards' => array( 'description' => esc_html__( "View people's profiles when you mouse over their Gravatars", 'jetpack' ), 'type' => 'string', 'default' => 'enabled', @@ -2438,14 +2438,14 @@ public static function get_updateable_data_list( $selector = '' ) { ), // Infinite Scroll. - 'infinite_scroll' => array( + 'infinite_scroll' => array( 'description' => esc_html__( 'To infinity and beyond', 'jetpack' ), 'type' => 'boolean', 'default' => 1, 'validate_callback' => __CLASS__ . '::validate_boolean', 'jp_group' => 'infinite-scroll', ), - 'infinite_scroll_google_analytics' => array( + 'infinite_scroll_google_analytics' => array( 'description' => esc_html__( 'Use Google Analytics with Infinite Scroll', 'jetpack' ), 'type' => 'boolean', 'default' => 0, @@ -2454,7 +2454,7 @@ public static function get_updateable_data_list( $selector = '' ) { ), // Likes. - 'wpl_default' => array( + 'wpl_default' => array( 'description' => esc_html__( 'WordPress.com Likes are', 'jetpack' ), 'type' => 'string', 'default' => 'on', @@ -2469,7 +2469,7 @@ public static function get_updateable_data_list( $selector = '' ) { 'validate_callback' => __CLASS__ . '::validate_list_item', 'jp_group' => 'likes', ), - 'social_notifications_like' => array( + 'social_notifications_like' => array( 'description' => esc_html__( 'Send email notification when someone likes a post', 'jetpack' ), 'type' => 'boolean', 'default' => 1, @@ -2478,14 +2478,14 @@ public static function get_updateable_data_list( $selector = '' ) { ), // Markdown. - 'wpcom_publish_comments_with_markdown' => array( + 'wpcom_publish_comments_with_markdown' => array( 'description' => esc_html__( 'Use Markdown for comments.', 'jetpack' ), 'type' => 'boolean', 'default' => 0, 'validate_callback' => __CLASS__ . '::validate_boolean', 'jp_group' => 'markdown', ), - 'wpcom_publish_posts_with_markdown' => array( + 'wpcom_publish_posts_with_markdown' => array( 'description' => esc_html__( 'Use Markdown for posts.', 'jetpack' ), 'type' => 'boolean', 'default' => 0, @@ -2494,7 +2494,7 @@ public static function get_updateable_data_list( $selector = '' ) { ), // Monitor. - 'monitor_receive_notifications' => array( + 'monitor_receive_notifications' => array( 'description' => esc_html__( 'Receive Monitor Email Notifications.', 'jetpack' ), 'type' => 'boolean', 'default' => 0, @@ -2503,7 +2503,7 @@ public static function get_updateable_data_list( $selector = '' ) { ), // Post by Email. - 'post_by_email_address' => array( + 'post_by_email_address' => array( 'description' => esc_html__( 'Email Address', 'jetpack' ), 'type' => 'string', 'default' => 'noop', @@ -2524,14 +2524,14 @@ public static function get_updateable_data_list( $selector = '' ) { ), // Protect. - 'jetpack_protect_key' => array( + 'jetpack_protect_key' => array( 'description' => esc_html__( 'Protect API key', 'jetpack' ), 'type' => 'string', 'default' => '', 'validate_callback' => __CLASS__ . '::validate_alphanum', 'jp_group' => 'protect', ), - 'jetpack_protect_global_whitelist' => array( + 'jetpack_protect_global_whitelist' => array( 'description' => esc_html__( 'Protect global IP allow list', 'jetpack' ), 'type' => 'string', 'default' => '', @@ -2541,7 +2541,7 @@ public static function get_updateable_data_list( $selector = '' ) { ), // Sharing. - 'sharing_services' => array( + 'sharing_services' => array( 'description' => esc_html__( 'Enabled Services and those hidden behind a button', 'jetpack' ), 'type' => 'object', 'default' => array( @@ -2551,7 +2551,7 @@ public static function get_updateable_data_list( $selector = '' ) { 'validate_callback' => __CLASS__ . '::validate_services', 'jp_group' => 'sharedaddy', ), - 'button_style' => array( + 'button_style' => array( 'description' => esc_html__( 'Button Style', 'jetpack' ), 'type' => 'string', 'default' => 'icon', @@ -2570,7 +2570,7 @@ public static function get_updateable_data_list( $selector = '' ) { 'validate_callback' => __CLASS__ . '::validate_list_item', 'jp_group' => 'sharedaddy', ), - 'sharing_label' => array( + 'sharing_label' => array( 'description' => esc_html__( 'Sharing Label', 'jetpack' ), 'type' => 'string', 'default' => '', @@ -2578,7 +2578,7 @@ public static function get_updateable_data_list( $selector = '' ) { 'sanitize_callback' => 'esc_html', 'jp_group' => 'sharedaddy', ), - 'show' => array( + 'show' => array( 'description' => esc_html__( 'Views where buttons are shown', 'jetpack' ), 'type' => 'array', 'items' => array( @@ -2588,7 +2588,7 @@ public static function get_updateable_data_list( $selector = '' ) { 'validate_callback' => __CLASS__ . '::validate_sharing_show', 'jp_group' => 'sharedaddy', ), - 'jetpack-twitter-cards-site-tag' => array( + 'jetpack-twitter-cards-site-tag' => array( 'description' => esc_html__( "The Twitter username of the owner of this site's domain.", 'jetpack' ), 'type' => 'string', 'default' => '', @@ -2596,14 +2596,14 @@ public static function get_updateable_data_list( $selector = '' ) { 'sanitize_callback' => 'esc_html', 'jp_group' => 'sharedaddy', ), - 'sharedaddy_disable_resources' => array( + 'sharedaddy_disable_resources' => array( 'description' => esc_html__( 'Disable CSS and JS', 'jetpack' ), 'type' => 'boolean', 'default' => 0, 'validate_callback' => __CLASS__ . '::validate_boolean', 'jp_group' => 'sharedaddy', ), - 'custom' => array( + 'custom' => array( 'description' => esc_html__( 'Custom sharing services added by user.', 'jetpack' ), 'type' => 'object', 'default' => array( @@ -2615,7 +2615,7 @@ public static function get_updateable_data_list( $selector = '' ) { 'jp_group' => 'sharedaddy', ), // Not an option, but an action that can be performed on the list of custom services passing the service ID. - 'sharing_delete_service' => array( + 'sharing_delete_service' => array( 'description' => esc_html__( 'Delete custom sharing service.', 'jetpack' ), 'type' => 'string', 'default' => '', @@ -2624,14 +2624,14 @@ public static function get_updateable_data_list( $selector = '' ) { ), // SSO. - 'jetpack_sso_require_two_step' => array( + 'jetpack_sso_require_two_step' => array( 'description' => esc_html__( 'Require Two-Step Authentication', 'jetpack' ), 'type' => 'boolean', 'default' => SSO\Helpers::is_require_two_step_checkbox_disabled(), 'validate_callback' => __CLASS__ . '::validate_boolean', 'jp_group' => 'sso', ), - 'jetpack_sso_match_by_email' => array( + 'jetpack_sso_match_by_email' => array( 'description' => esc_html__( 'Match by Email', 'jetpack' ), 'type' => 'boolean', 'default' => 1, @@ -2640,97 +2640,104 @@ public static function get_updateable_data_list( $selector = '' ) { ), // Subscriptions. - 'stb_enabled' => array( + 'stb_enabled' => array( 'description' => esc_html__( "Show a 'follow blog' option in the comment form", 'jetpack' ), 'type' => 'boolean', 'default' => 1, 'validate_callback' => __CLASS__ . '::validate_boolean', 'jp_group' => 'subscriptions', ), - 'stc_enabled' => array( + 'stc_enabled' => array( 'description' => esc_html__( "Show a 'follow comments' option in the comment form", 'jetpack' ), 'type' => 'boolean', 'default' => 1, 'validate_callback' => __CLASS__ . '::validate_boolean', 'jp_group' => 'subscriptions', ), - 'wpcom_newsletter_categories' => array( + 'wpcom_newsletter_categories' => array( 'description' => esc_html__( 'Array of post category ids that are marked as newsletter categories', 'jetpack' ), 'type' => 'array', 'default' => array(), 'validate_callback' => __CLASS__ . '::validate_array', 'jp_group' => 'subscriptions', ), - 'wpcom_newsletter_categories_enabled' => array( + 'wpcom_newsletter_categories_enabled' => array( 'description' => esc_html__( 'Whether the newsletter categories are enabled or not', 'jetpack' ), 'type' => 'boolean', 'default' => 0, 'validate_callback' => __CLASS__ . '::validate_boolean', 'jp_group' => 'subscriptions', ), - 'wpcom_featured_image_in_email' => array( + 'wpcom_featured_image_in_email' => array( 'description' => esc_html__( 'Whether to include the featured image in the email or not', 'jetpack' ), 'type' => 'boolean', 'default' => 0, 'validate_callback' => __CLASS__ . '::validate_boolean', 'jp_group' => 'subscriptions', ), - 'jetpack_gravatar_in_email' => array( + 'jetpack_gravatar_in_email' => array( 'description' => esc_html__( 'Whether to show author avatar in the email byline', 'jetpack' ), 'type' => 'boolean', 'default' => 1, 'validate_callback' => __CLASS__ . '::validate_boolean', 'jp_group' => 'subscriptions', ), - 'jetpack_author_in_email' => array( + 'jetpack_author_in_email' => array( 'description' => esc_html__( 'Whether to show author display name in the email byline', 'jetpack' ), 'type' => 'boolean', 'default' => 1, 'validate_callback' => __CLASS__ . '::validate_boolean', 'jp_group' => 'subscriptions', ), - 'jetpack_post_date_in_email' => array( + 'jetpack_post_date_in_email' => array( 'description' => esc_html__( 'Whether to show date in the email byline', 'jetpack' ), 'type' => 'boolean', 'default' => 1, 'validate_callback' => __CLASS__ . '::validate_boolean', 'jp_group' => 'subscriptions', ), - 'wpcom_subscription_emails_use_excerpt' => array( + 'wpcom_subscription_emails_use_excerpt' => array( 'description' => esc_html__( 'Whether to use the excerpt in the email or not', 'jetpack' ), 'type' => 'boolean', 'default' => 0, 'validate_callback' => __CLASS__ . '::validate_boolean', 'jp_group' => 'subscriptions', ), - 'jetpack_subscriptions_reply_to' => array( + 'jetpack_subscriptions_reply_to' => array( 'description' => esc_html__( 'Reply to email behaviour for newsletters emails', 'jetpack' ), 'type' => 'string', 'default' => Automattic\Jetpack\Modules\Subscriptions\Settings::$default_reply_to, 'validate_callback' => __CLASS__ . '::validate_subscriptions_reply_to', 'jp_group' => 'subscriptions', ), - 'jetpack_subscriptions_from_name' => array( + 'jetpack_subscriptions_from_name' => array( 'description' => esc_html__( 'From name for newsletters emails', 'jetpack' ), 'type' => 'string', 'default' => '', 'validate_callback' => __CLASS__ . '::validate_subscriptions_reply_to_name', 'jp_group' => 'subscriptions', ), - 'sm_enabled' => array( + 'sm_enabled' => array( 'description' => esc_html__( 'Show popup Subscribe modal to readers.', 'jetpack' ), 'type' => 'boolean', 'default' => 0, 'validate_callback' => __CLASS__ . '::validate_boolean', 'jp_group' => 'subscriptions', ), - 'jetpack_subscribe_overlay_enabled' => array( + 'jetpack_subscribe_overlay_enabled' => array( 'description' => esc_html__( 'Show subscribe overlay on homepage.', 'jetpack' ), 'type' => 'boolean', 'default' => 0, 'validate_callback' => __CLASS__ . '::validate_boolean', 'jp_group' => 'subscriptions', ), + 'jetpack_subscribe_floating_button_enabled' => array( + 'description' => esc_html__( 'Show a floating subscribe button.', 'jetpack' ), + 'type' => 'boolean', + 'default' => 0, + 'validate_callback' => __CLASS__ . '::validate_boolean', + 'jp_group' => 'subscriptions', + ), 'jetpack_subscriptions_subscribe_post_end_enabled' => array( 'description' => esc_html__( 'Add Subscribe block at the end of each post.', 'jetpack' ), 'type' => 'boolean', @@ -2752,14 +2759,14 @@ public static function get_updateable_data_list( $selector = '' ) { 'validate_callback' => __CLASS__ . '::validate_boolean', 'jp_group' => 'subscriptions', ), - 'social_notifications_subscribe' => array( + 'social_notifications_subscribe' => array( 'description' => esc_html__( 'Send email notification when someone subscribes to my blog', 'jetpack' ), 'type' => 'boolean', 'default' => 0, 'validate_callback' => __CLASS__ . '::validate_boolean', 'jp_group' => 'subscriptions', ), - 'subscription_options' => array( + 'subscription_options' => array( 'description' => esc_html__( 'Three options used in subscription email templates: \'invitation\', \'welcome\' and \'comment_follow\'.', 'jetpack' ), 'type' => 'object', 'default' => array( @@ -2772,14 +2779,14 @@ public static function get_updateable_data_list( $selector = '' ) { ), // Related Posts. - 'show_headline' => array( + 'show_headline' => array( 'description' => esc_html__( 'Highlight related content with a heading', 'jetpack' ), 'type' => 'boolean', 'default' => 1, 'validate_callback' => __CLASS__ . '::validate_boolean', 'jp_group' => 'related-posts', ), - 'show_thumbnails' => array( + 'show_thumbnails' => array( 'description' => esc_html__( 'Show a thumbnail image where available', 'jetpack' ), 'type' => 'boolean', 'default' => 0, @@ -2788,7 +2795,7 @@ public static function get_updateable_data_list( $selector = '' ) { ), // Search. - 'instant_search_enabled' => array( + 'instant_search_enabled' => array( 'description' => esc_html__( 'Enable Instant Search', 'jetpack' ), 'type' => 'boolean', 'default' => 0, @@ -2796,7 +2803,7 @@ public static function get_updateable_data_list( $selector = '' ) { 'jp_group' => 'search', ), - 'has_jetpack_search_product' => array( + 'has_jetpack_search_product' => array( 'description' => esc_html__( 'Has an active Jetpack Search product purchase', 'jetpack' ), 'type' => 'boolean', 'default' => 0, @@ -2804,7 +2811,7 @@ public static function get_updateable_data_list( $selector = '' ) { 'jp_group' => 'settings', ), - 'search_auto_config' => array( + 'search_auto_config' => array( 'description' => esc_html__( 'Trigger an auto config of instant search', 'jetpack' ), 'type' => 'boolean', 'default' => 0, @@ -2813,35 +2820,35 @@ public static function get_updateable_data_list( $selector = '' ) { ), // Verification Tools. - 'google' => array( + 'google' => array( 'description' => esc_html__( 'Google Search Console', 'jetpack' ), 'type' => 'string', 'default' => '', 'validate_callback' => __CLASS__ . '::validate_verification_service', 'jp_group' => 'verification-tools', ), - 'bing' => array( + 'bing' => array( 'description' => esc_html__( 'Bing Webmaster Center', 'jetpack' ), 'type' => 'string', 'default' => '', 'validate_callback' => __CLASS__ . '::validate_verification_service', 'jp_group' => 'verification-tools', ), - 'pinterest' => array( + 'pinterest' => array( 'description' => esc_html__( 'Pinterest Site Verification', 'jetpack' ), 'type' => 'string', 'default' => '', 'validate_callback' => __CLASS__ . '::validate_verification_service', 'jp_group' => 'verification-tools', ), - 'yandex' => array( + 'yandex' => array( 'description' => esc_html__( 'Yandex Site Verification', 'jetpack' ), 'type' => 'string', 'default' => '', 'validate_callback' => __CLASS__ . '::validate_verification_service', 'jp_group' => 'verification-tools', ), - 'facebook' => array( + 'facebook' => array( 'description' => esc_html__( 'Facebook Domain Verification', 'jetpack' ), 'type' => 'string', 'default' => '', @@ -2850,70 +2857,70 @@ public static function get_updateable_data_list( $selector = '' ) { ), // WordAds. - 'enable_header_ad' => array( + 'enable_header_ad' => array( 'description' => esc_html__( 'Display an ad unit at the top of each page.', 'jetpack' ), 'type' => 'boolean', 'default' => 1, 'validate_callback' => __CLASS__ . '::validate_boolean', 'jp_group' => 'wordads', ), - 'wordads_approved' => array( + 'wordads_approved' => array( 'description' => esc_html__( 'Is site approved for WordAds?', 'jetpack' ), 'type' => 'boolean', 'default' => 0, 'validate_callback' => __CLASS__ . '::validate_boolean', 'jp_group' => 'wordads', ), - 'wordads_second_belowpost' => array( + 'wordads_second_belowpost' => array( 'description' => esc_html__( 'Display second ad below post?', 'jetpack' ), 'type' => 'boolean', 'default' => 1, 'validate_callback' => __CLASS__ . '::validate_boolean', 'jp_group' => 'wordads', ), - 'wordads_inline_enabled' => array( + 'wordads_inline_enabled' => array( 'description' => esc_html__( 'Display inline ad within post content?', 'jetpack' ), 'type' => 'boolean', 'default' => 1, 'validate_callback' => __CLASS__ . '::validate_boolean', 'jp_group' => 'wordads', ), - 'wordads_display_front_page' => array( + 'wordads_display_front_page' => array( 'description' => esc_html__( 'Display ads on the front page?', 'jetpack' ), 'type' => 'boolean', 'default' => 1, 'validate_callback' => __CLASS__ . '::validate_boolean', 'jp_group' => 'wordads', ), - 'wordads_display_post' => array( + 'wordads_display_post' => array( 'description' => esc_html__( 'Display ads on posts?', 'jetpack' ), 'type' => 'boolean', 'default' => 1, 'validate_callback' => __CLASS__ . '::validate_boolean', 'jp_group' => 'wordads', ), - 'wordads_display_page' => array( + 'wordads_display_page' => array( 'description' => esc_html__( 'Display ads on pages?', 'jetpack' ), 'type' => 'boolean', 'default' => 1, 'validate_callback' => __CLASS__ . '::validate_boolean', 'jp_group' => 'wordads', ), - 'wordads_display_archive' => array( + 'wordads_display_archive' => array( 'description' => esc_html__( 'Display ads on archive pages?', 'jetpack' ), 'type' => 'boolean', 'default' => 1, 'validate_callback' => __CLASS__ . '::validate_boolean', 'jp_group' => 'wordads', ), - 'wordads_custom_adstxt_enabled' => array( + 'wordads_custom_adstxt_enabled' => array( 'description' => esc_html__( 'Custom ads.txt', 'jetpack' ), 'type' => 'boolean', 'default' => 0, 'validate_callback' => __CLASS__ . '::validate_boolean', 'jp_group' => 'wordads', ), - 'wordads_custom_adstxt' => array( + 'wordads_custom_adstxt' => array( 'description' => esc_html__( 'Custom ads.txt entries', 'jetpack' ), 'type' => 'string', 'default' => '', @@ -2921,14 +2928,14 @@ public static function get_updateable_data_list( $selector = '' ) { 'sanitize_callback' => 'sanitize_textarea_field', 'jp_group' => 'wordads', ), - 'wordads_ccpa_enabled' => array( + 'wordads_ccpa_enabled' => array( 'description' => esc_html__( 'Enable support for California Consumer Privacy Act', 'jetpack' ), 'type' => 'boolean', 'default' => 0, 'validate_callback' => __CLASS__ . '::validate_boolean', 'jp_group' => 'wordads', ), - 'wordads_ccpa_privacy_policy_url' => array( + 'wordads_ccpa_privacy_policy_url' => array( 'description' => esc_html__( 'Privacy Policy URL', 'jetpack' ), 'type' => 'string', 'default' => '', @@ -2936,7 +2943,7 @@ public static function get_updateable_data_list( $selector = '' ) { 'sanitize_callback' => 'sanitize_text_field', 'jp_group' => 'wordads', ), - 'wordads_cmp_enabled' => array( + 'wordads_cmp_enabled' => array( 'description' => esc_html__( 'Enable GDPR Consent Management Banner for WordAds', 'jetpack' ), 'type' => 'boolean', 'default' => 0, @@ -2945,7 +2952,7 @@ public static function get_updateable_data_list( $selector = '' ) { ), // Google Analytics. - 'google_analytics_tracking_id' => array( + 'google_analytics_tracking_id' => array( 'description' => esc_html__( 'Google Analytics', 'jetpack' ), 'type' => 'string', 'default' => '', @@ -2954,21 +2961,21 @@ public static function get_updateable_data_list( $selector = '' ) { ), // Stats. - 'admin_bar' => array( + 'admin_bar' => array( 'description' => esc_html__( 'Include a small chart in your admin bar with a 48-hour traffic snapshot.', 'jetpack' ), 'type' => 'boolean', 'default' => 1, 'validate_callback' => __CLASS__ . '::validate_boolean', 'jp_group' => 'stats', ), - 'enable_odyssey_stats' => array( + 'enable_odyssey_stats' => array( 'description' => esc_html__( 'Preview the new Jetpack Stats experience (Experimental).', 'jetpack' ), 'type' => 'boolean', 'default' => 1, 'validate_callback' => __CLASS__ . '::validate_boolean', 'jp_group' => 'stats', ), - 'roles' => array( + 'roles' => array( 'description' => esc_html__( 'Select the roles that will be able to view stats reports.', 'jetpack' ), 'type' => 'array', 'items' => array( @@ -2979,7 +2986,7 @@ public static function get_updateable_data_list( $selector = '' ) { 'sanitize_callback' => __CLASS__ . '::sanitize_stats_allowed_roles', 'jp_group' => 'stats', ), - 'count_roles' => array( + 'count_roles' => array( 'description' => esc_html__( 'Count the page views of registered users who are logged in.', 'jetpack' ), 'type' => 'array', 'items' => array( @@ -2989,28 +2996,28 @@ public static function get_updateable_data_list( $selector = '' ) { 'validate_callback' => __CLASS__ . '::validate_stats_roles', 'jp_group' => 'stats', ), - 'blog_id' => array( + 'blog_id' => array( 'description' => esc_html__( 'Blog ID.', 'jetpack' ), 'type' => 'boolean', 'default' => 0, 'validate_callback' => __CLASS__ . '::validate_boolean', 'jp_group' => 'stats', ), - 'do_not_track' => array( + 'do_not_track' => array( 'description' => esc_html__( 'Do not track.', 'jetpack' ), 'type' => 'boolean', 'default' => 1, 'validate_callback' => __CLASS__ . '::validate_boolean', 'jp_group' => 'stats', ), - 'version' => array( + 'version' => array( 'description' => esc_html__( 'Version.', 'jetpack' ), 'type' => 'integer', 'default' => 9, 'validate_callback' => __CLASS__ . '::validate_posint', 'jp_group' => 'stats', ), - 'collapse_nudges' => array( + 'collapse_nudges' => array( 'description' => esc_html__( 'Collapse upgrade nudges', 'jetpack' ), 'type' => 'boolean', 'default' => 0, @@ -3019,7 +3026,7 @@ public static function get_updateable_data_list( $selector = '' ) { ), // Whether to share stats views with WordPress.com Reader. - 'wpcom_reader_views_enabled' => array( + 'wpcom_reader_views_enabled' => array( 'description' => esc_html__( 'Show post views in the WordPress.com Reader.', 'jetpack' ), 'type' => 'boolean', 'default' => 1, @@ -3028,7 +3035,7 @@ public static function get_updateable_data_list( $selector = '' ) { ), // Akismet - Not a module, but a plugin. The options can be passed and handled differently. - 'akismet_show_user_comments_approved' => array( + 'akismet_show_user_comments_approved' => array( 'description' => '', 'type' => 'boolean', 'default' => 0, @@ -3036,7 +3043,7 @@ public static function get_updateable_data_list( $selector = '' ) { 'jp_group' => 'settings', ), - 'wordpress_api_key' => array( + 'wordpress_api_key' => array( 'description' => '', 'type' => 'string', 'default' => '', @@ -3045,7 +3052,7 @@ public static function get_updateable_data_list( $selector = '' ) { ), // Empty stats card dismiss. - 'dismiss_empty_stats_card' => array( + 'dismiss_empty_stats_card' => array( 'description' => '', 'type' => 'boolean', 'default' => 0, @@ -3054,7 +3061,7 @@ public static function get_updateable_data_list( $selector = '' ) { ), // Backup Getting Started card on dashboard. - 'dismiss_dash_backup_getting_started' => array( + 'dismiss_dash_backup_getting_started' => array( 'description' => '', 'type' => 'boolean', 'default' => 0, @@ -3063,7 +3070,7 @@ public static function get_updateable_data_list( $selector = '' ) { ), // Agencies Learn More card on dashboard. - 'dismiss_dash_agencies_learn_more' => array( + 'dismiss_dash_agencies_learn_more' => array( 'description' => '', 'type' => 'boolean', 'default' => 0, @@ -3071,7 +3078,7 @@ public static function get_updateable_data_list( $selector = '' ) { 'jp_group' => 'settings', ), - 'lang_id' => array( + 'lang_id' => array( 'description' => esc_html__( 'Primary language for the site.', 'jetpack' ), 'type' => 'string', 'default' => 'en_US', @@ -3079,7 +3086,7 @@ public static function get_updateable_data_list( $selector = '' ) { ), // SEO Tools. - 'advanced_seo_front_page_description' => array( + 'advanced_seo_front_page_description' => array( 'description' => esc_html__( 'Front page meta description.', 'jetpack' ), 'type' => 'string', 'default' => '', @@ -3087,7 +3094,7 @@ public static function get_updateable_data_list( $selector = '' ) { 'jp_group' => 'seo-tools', ), - 'advanced_seo_title_formats' => array( + 'advanced_seo_title_formats' => array( 'description' => esc_html__( 'SEO page title structures.', 'jetpack' ), 'type' => 'object', 'default' => array( @@ -3103,7 +3110,7 @@ public static function get_updateable_data_list( $selector = '' ) { ), // VideoPress. - 'videopress_private_enabled_for_site' => array( + 'videopress_private_enabled_for_site' => array( 'description' => esc_html__( 'Video Privacy: Restrict views to members of this site', 'jetpack' ), 'type' => 'boolean', 'default' => 0, diff --git a/projects/plugins/jetpack/_inc/lib/core-api/class.jetpack-core-api-module-endpoints.php b/projects/plugins/jetpack/_inc/lib/core-api/class.jetpack-core-api-module-endpoints.php index d6419f99740c6..9aa7ab1f03673 100644 --- a/projects/plugins/jetpack/_inc/lib/core-api/class.jetpack-core-api-module-endpoints.php +++ b/projects/plugins/jetpack/_inc/lib/core-api/class.jetpack-core-api-module-endpoints.php @@ -966,6 +966,7 @@ public function update_data( $request ) { case 'stc_enabled': case 'sm_enabled': case 'jetpack_subscribe_overlay_enabled': + case 'jetpack_subscribe_floating_button_enabled': case 'wpcom_newsletter_categories_enabled': case 'wpcom_featured_image_in_email': case 'jetpack_gravatar_in_email': diff --git a/projects/plugins/jetpack/changelog/add-floating-subscribe-button b/projects/plugins/jetpack/changelog/add-floating-subscribe-button new file mode 100644 index 0000000000000..80566f7f8a5b2 --- /dev/null +++ b/projects/plugins/jetpack/changelog/add-floating-subscribe-button @@ -0,0 +1,4 @@ +Significance: minor +Type: enhancement + +Subscriptions: add a floating subscribe button diff --git a/projects/plugins/jetpack/changelog/add-jetpack-ai-logo-generator-styles-instructions b/projects/plugins/jetpack/changelog/add-jetpack-ai-logo-generator-styles-instructions new file mode 100644 index 0000000000000..9c813a1ba3abf --- /dev/null +++ b/projects/plugins/jetpack/changelog/add-jetpack-ai-logo-generator-styles-instructions @@ -0,0 +1,4 @@ +Significance: patch +Type: other + +Jetpack AI: add instructions on to-test file diff --git a/projects/plugins/jetpack/changelog/change-jetpack-ai-fetch-error-retry-optional b/projects/plugins/jetpack/changelog/change-jetpack-ai-fetch-error-retry-optional new file mode 100644 index 0000000000000..38baa75852ac8 --- /dev/null +++ b/projects/plugins/jetpack/changelog/change-jetpack-ai-fetch-error-retry-optional @@ -0,0 +1,4 @@ +Significance: patch +Type: other + +Jetpack AI: remove reload handler for logo generator modal call diff --git a/projects/plugins/jetpack/changelog/fix-upload-media-endpoint-fatal b/projects/plugins/jetpack/changelog/fix-upload-media-endpoint-fatal new file mode 100644 index 0000000000000..1a93173ded991 --- /dev/null +++ b/projects/plugins/jetpack/changelog/fix-upload-media-endpoint-fatal @@ -0,0 +1,4 @@ +Significance: patch +Type: other + +WPCOM_JSON_API_Upload_Media_v1_1_Endpoint: Fix Fatals from uploads with invalid media type diff --git a/projects/plugins/jetpack/changelog/revert-39658-update-jetpack-sync-whitelist b/projects/plugins/jetpack/changelog/revert-39658-update-jetpack-sync-whitelist new file mode 100644 index 0000000000000..760eebb59c7fe --- /dev/null +++ b/projects/plugins/jetpack/changelog/revert-39658-update-jetpack-sync-whitelist @@ -0,0 +1,5 @@ +Significance: patch +Type: other +Comment: Update unit tests + + diff --git a/projects/plugins/jetpack/changelog/update-floating-subscribe-button-source b/projects/plugins/jetpack/changelog/update-floating-subscribe-button-source new file mode 100644 index 0000000000000..c31ed74d6a395 --- /dev/null +++ b/projects/plugins/jetpack/changelog/update-floating-subscribe-button-source @@ -0,0 +1,4 @@ +Significance: minor +Type: other + +Floating subscribe button: add source attribute for stats diff --git a/projects/plugins/jetpack/changelog/update-narrow-down-stats-bar-hook b/projects/plugins/jetpack/changelog/update-narrow-down-stats-bar-hook new file mode 100644 index 0000000000000..1eff8c83b266e --- /dev/null +++ b/projects/plugins/jetpack/changelog/update-narrow-down-stats-bar-hook @@ -0,0 +1,4 @@ +Significance: patch +Type: other + +Optimize the Stats Admin Bar hook by narrowing down the callback. diff --git a/projects/plugins/jetpack/extensions/extended-blocks/core-site-logo/index.tsx b/projects/plugins/jetpack/extensions/extended-blocks/core-site-logo/index.tsx index 233e96aad4a65..6d34c34b5c0ac 100644 --- a/projects/plugins/jetpack/extensions/extended-blocks/core-site-logo/index.tsx +++ b/projects/plugins/jetpack/extensions/extended-blocks/core-site-logo/index.tsx @@ -102,10 +102,10 @@ const siteLogoEditWithAiComponents = createHigherOrderComponent( BlockEdit => { setIsLogoGeneratorModalVisible( false ); }, [] ); - const reloadModal = useCallback( () => { - closeModal(); - showModal(); - }, [ closeModal, showModal ] ); + // const reloadModal = useCallback( () => { + // closeModal(); + // showModal(); + // }, [ closeModal, showModal ] ); const applyLogoHandler = useCallback( ( mediaId: number ) => { @@ -135,7 +135,8 @@ const siteLogoEditWithAiComponents = createHigherOrderComponent( BlockEdit => { isOpen={ isLogoGeneratorModalVisible } onClose={ closeModal } onApplyLogo={ applyLogoHandler } - onReload={ reloadModal } + // reload is not working right and can end up showing a non functional modal + // onReload={ reloadModal } context={ PLACEMENT_CONTEXT } placement={ TOOL_PLACEMENT } siteDetails={ siteDetails } diff --git a/projects/plugins/jetpack/json-endpoints/class.wpcom-json-api-site-settings-endpoint.php b/projects/plugins/jetpack/json-endpoints/class.wpcom-json-api-site-settings-endpoint.php index 308287ee323f9..9852478a7c53d 100644 --- a/projects/plugins/jetpack/json-endpoints/class.wpcom-json-api-site-settings-endpoint.php +++ b/projects/plugins/jetpack/json-endpoints/class.wpcom-json-api-site-settings-endpoint.php @@ -45,94 +45,95 @@ ), 'request_format' => array( - 'migration_source_site_domain' => '(string) The source site URL, from the migration flow', - 'in_site_migration_flow' => '(string) The migration flow the site is in', - 'blogname' => '(string) Blog name', - 'blogdescription' => '(string) Blog description', - 'default_pingback_flag' => '(bool) Notify blogs linked from article?', - 'default_ping_status' => '(bool) Allow link notifications from other blogs?', - 'default_comment_status' => '(bool) Allow comments on new articles?', - 'blog_public' => '(string) Site visibility; -1: private, 0: discourage search engines, 1: allow search engines', - 'wpcom_data_sharing_opt_out' => '(bool) Did the site opt out of sharing public content with third parties and research partners?', - 'jetpack_sync_non_public_post_stati' => '(bool) allow sync of post and pages with non-public posts stati', - 'jetpack_relatedposts_enabled' => '(bool) Enable related posts?', - 'jetpack_relatedposts_show_context' => '(bool) Show post\'s tags and category in related posts?', - 'jetpack_relatedposts_show_date' => '(bool) Show date in related posts?', - 'jetpack_relatedposts_show_headline' => '(bool) Show headline in related posts?', - 'jetpack_relatedposts_show_thumbnails' => '(bool) Show thumbnails in related posts?', - 'jetpack_protect_whitelist' => '(array) List of IP addresses to always allow', - 'instant_search_enabled' => '(bool) Enable the new Jetpack Instant Search interface', - 'jetpack_search_enabled' => '(bool) Enable Jetpack Search', - 'jetpack_search_supported' => '(bool) Jetpack Search is supported', - 'infinite_scroll' => '(bool) Support infinite scroll of posts?', - 'default_category' => '(int) Default post category', - 'default_post_format' => '(string) Default post format', - 'require_name_email' => '(bool) Require comment authors to fill out name and email?', - 'comment_registration' => '(bool) Require users to be registered and logged in to comment?', - 'close_comments_for_old_posts' => '(bool) Automatically close comments on old posts?', - 'close_comments_days_old' => '(int) Age at which to close comments', - 'thread_comments' => '(bool) Enable threaded comments?', - 'thread_comments_depth' => '(int) Depth to thread comments', - 'page_comments' => '(bool) Break comments into pages?', - 'comments_per_page' => '(int) Number of comments to display per page', - 'default_comments_page' => '(string) newest|oldest Which page of comments to display first', - 'comment_order' => '(string) asc|desc Order to display comments within page', - 'comments_notify' => '(bool) Email me when someone comments?', - 'moderation_notify' => '(bool) Email me when a comment is helf for moderation?', - 'social_notifications_like' => '(bool) Email me when someone likes my post?', - 'social_notifications_reblog' => '(bool) Email me when someone reblogs my post?', - 'social_notifications_subscribe' => '(bool) Email me when someone subscribes to my blog?', - 'comment_moderation' => '(bool) Moderate comments for manual approval?', - 'comment_previously_approved' => '(bool) Moderate comments unless author has a previously-approved comment?', - 'comment_max_links' => '(int) Moderate comments that contain X or more links', - 'moderation_keys' => '(string) Words or phrases that trigger comment moderation, one per line', - 'disallowed_keys' => '(string) Words or phrases that mark comment spam, one per line', - 'lang_id' => '(int) ID for language blog is written in', - 'wga' => '(array) Google Analytics Settings', - 'disabled_likes' => '(bool) Are likes globally disabled (they can still be turned on per post)?', - 'disabled_reblogs' => '(bool) Are reblogs disabled on posts?', - 'jetpack_comment_likes_enabled' => '(bool) Are comment likes enabled for all comments?', - 'sharing_button_style' => '(string) Style to use for sharing buttons (icon-text, icon, text, or official)', - 'sharing_label' => '(string) Label to use for sharing buttons, e.g. "Share this:"', - 'sharing_show' => '(string|array:string) Post type or array of types where sharing buttons are to be displayed', - 'sharing_open_links' => '(string) Link target for sharing buttons (same or new)', - 'twitter_via' => '(string) Twitter username to include in tweets when people share using the Twitter button', - 'jetpack-twitter-cards-site-tag' => '(string) The Twitter username of the owner of the site\'s domain.', - 'eventbrite_api_token' => '(int) The Keyring token ID for an Eventbrite token to associate with the site', - 'timezone_string' => '(string) PHP-compatible timezone string like \'UTC-5\'', - 'gmt_offset' => '(int) Site offset from UTC in hours', - 'date_format' => '(string) PHP Date-compatible date format', - 'time_format' => '(string) PHP Date-compatible time format', - 'start_of_week' => '(int) Starting day of week (0 = Sunday, 6 = Saturday)', - 'jetpack_testimonial' => '(bool) Whether testimonial custom post type is enabled for the site', - 'jetpack_testimonial_posts_per_page' => '(int) Number of testimonials to show per page', - 'jetpack_portfolio' => '(bool) Whether portfolio custom post type is enabled for the site', - 'jetpack_portfolio_posts_per_page' => '(int) Number of portfolio projects to show per page', - Jetpack_SEO_Utils::FRONT_PAGE_META_OPTION => '(string) The seo meta description for the site.', - Jetpack_SEO_Titles::TITLE_FORMATS_OPTION => '(array) SEO meta title formats. Allowed keys: front_page, posts, pages, groups, archives', - 'verification_services_codes' => '(array) Website verification codes. Allowed keys: google, pinterest, bing, yandex, facebook', - 'markdown_supported' => '(bool) Whether markdown is supported for this site', - 'wpcom_publish_posts_with_markdown' => '(bool) Whether markdown is enabled for posts', - 'wpcom_publish_comments_with_markdown' => '(bool) Whether markdown is enabled for comments', - 'site_icon' => '(int) Media attachment ID to use as site icon. Set to zero or an otherwise empty value to clear', - 'api_cache' => '(bool) Turn on/off the Jetpack JSON API cache', - 'posts_per_page' => '(int) Number of posts to show on blog pages', - 'posts_per_rss' => '(int) Number of posts to show in the RSS feed', - 'rss_use_excerpt' => '(bool) Whether the RSS feed will use post excerpts', - 'launchpad_screen' => '(string) Whether or not launchpad is presented and what size it will be', - 'sm_enabled' => '(bool) Whether the newsletter subscribe modal is enabled', - 'jetpack_subscribe_overlay_enabled' => '(bool) Whether the newsletter subscribe overlay is enabled', + 'migration_source_site_domain' => '(string) The source site URL, from the migration flow', + 'in_site_migration_flow' => '(string) The migration flow the site is in', + 'blogname' => '(string) Blog name', + 'blogdescription' => '(string) Blog description', + 'default_pingback_flag' => '(bool) Notify blogs linked from article?', + 'default_ping_status' => '(bool) Allow link notifications from other blogs?', + 'default_comment_status' => '(bool) Allow comments on new articles?', + 'blog_public' => '(string) Site visibility; -1: private, 0: discourage search engines, 1: allow search engines', + 'wpcom_data_sharing_opt_out' => '(bool) Did the site opt out of sharing public content with third parties and research partners?', + 'jetpack_sync_non_public_post_stati' => '(bool) allow sync of post and pages with non-public posts stati', + 'jetpack_relatedposts_enabled' => '(bool) Enable related posts?', + 'jetpack_relatedposts_show_context' => '(bool) Show post\'s tags and category in related posts?', + 'jetpack_relatedposts_show_date' => '(bool) Show date in related posts?', + 'jetpack_relatedposts_show_headline' => '(bool) Show headline in related posts?', + 'jetpack_relatedposts_show_thumbnails' => '(bool) Show thumbnails in related posts?', + 'jetpack_protect_whitelist' => '(array) List of IP addresses to always allow', + 'instant_search_enabled' => '(bool) Enable the new Jetpack Instant Search interface', + 'jetpack_search_enabled' => '(bool) Enable Jetpack Search', + 'jetpack_search_supported' => '(bool) Jetpack Search is supported', + 'infinite_scroll' => '(bool) Support infinite scroll of posts?', + 'default_category' => '(int) Default post category', + 'default_post_format' => '(string) Default post format', + 'require_name_email' => '(bool) Require comment authors to fill out name and email?', + 'comment_registration' => '(bool) Require users to be registered and logged in to comment?', + 'close_comments_for_old_posts' => '(bool) Automatically close comments on old posts?', + 'close_comments_days_old' => '(int) Age at which to close comments', + 'thread_comments' => '(bool) Enable threaded comments?', + 'thread_comments_depth' => '(int) Depth to thread comments', + 'page_comments' => '(bool) Break comments into pages?', + 'comments_per_page' => '(int) Number of comments to display per page', + 'default_comments_page' => '(string) newest|oldest Which page of comments to display first', + 'comment_order' => '(string) asc|desc Order to display comments within page', + 'comments_notify' => '(bool) Email me when someone comments?', + 'moderation_notify' => '(bool) Email me when a comment is helf for moderation?', + 'social_notifications_like' => '(bool) Email me when someone likes my post?', + 'social_notifications_reblog' => '(bool) Email me when someone reblogs my post?', + 'social_notifications_subscribe' => '(bool) Email me when someone subscribes to my blog?', + 'comment_moderation' => '(bool) Moderate comments for manual approval?', + 'comment_previously_approved' => '(bool) Moderate comments unless author has a previously-approved comment?', + 'comment_max_links' => '(int) Moderate comments that contain X or more links', + 'moderation_keys' => '(string) Words or phrases that trigger comment moderation, one per line', + 'disallowed_keys' => '(string) Words or phrases that mark comment spam, one per line', + 'lang_id' => '(int) ID for language blog is written in', + 'wga' => '(array) Google Analytics Settings', + 'disabled_likes' => '(bool) Are likes globally disabled (they can still be turned on per post)?', + 'disabled_reblogs' => '(bool) Are reblogs disabled on posts?', + 'jetpack_comment_likes_enabled' => '(bool) Are comment likes enabled for all comments?', + 'sharing_button_style' => '(string) Style to use for sharing buttons (icon-text, icon, text, or official)', + 'sharing_label' => '(string) Label to use for sharing buttons, e.g. "Share this:"', + 'sharing_show' => '(string|array:string) Post type or array of types where sharing buttons are to be displayed', + 'sharing_open_links' => '(string) Link target for sharing buttons (same or new)', + 'twitter_via' => '(string) Twitter username to include in tweets when people share using the Twitter button', + 'jetpack-twitter-cards-site-tag' => '(string) The Twitter username of the owner of the site\'s domain.', + 'eventbrite_api_token' => '(int) The Keyring token ID for an Eventbrite token to associate with the site', + 'timezone_string' => '(string) PHP-compatible timezone string like \'UTC-5\'', + 'gmt_offset' => '(int) Site offset from UTC in hours', + 'date_format' => '(string) PHP Date-compatible date format', + 'time_format' => '(string) PHP Date-compatible time format', + 'start_of_week' => '(int) Starting day of week (0 = Sunday, 6 = Saturday)', + 'jetpack_testimonial' => '(bool) Whether testimonial custom post type is enabled for the site', + 'jetpack_testimonial_posts_per_page' => '(int) Number of testimonials to show per page', + 'jetpack_portfolio' => '(bool) Whether portfolio custom post type is enabled for the site', + 'jetpack_portfolio_posts_per_page' => '(int) Number of portfolio projects to show per page', + Jetpack_SEO_Utils::FRONT_PAGE_META_OPTION => '(string) The seo meta description for the site.', + Jetpack_SEO_Titles::TITLE_FORMATS_OPTION => '(array) SEO meta title formats. Allowed keys: front_page, posts, pages, groups, archives', + 'verification_services_codes' => '(array) Website verification codes. Allowed keys: google, pinterest, bing, yandex, facebook', + 'markdown_supported' => '(bool) Whether markdown is supported for this site', + 'wpcom_publish_posts_with_markdown' => '(bool) Whether markdown is enabled for posts', + 'wpcom_publish_comments_with_markdown' => '(bool) Whether markdown is enabled for comments', + 'site_icon' => '(int) Media attachment ID to use as site icon. Set to zero or an otherwise empty value to clear', + 'api_cache' => '(bool) Turn on/off the Jetpack JSON API cache', + 'posts_per_page' => '(int) Number of posts to show on blog pages', + 'posts_per_rss' => '(int) Number of posts to show in the RSS feed', + 'rss_use_excerpt' => '(bool) Whether the RSS feed will use post excerpts', + 'launchpad_screen' => '(string) Whether or not launchpad is presented and what size it will be', + 'sm_enabled' => '(bool) Whether the newsletter subscribe modal is enabled', + 'jetpack_subscribe_overlay_enabled' => '(bool) Whether the newsletter subscribe overlay is enabled', + 'jetpack_subscribe_floating_button_enabled' => '(bool) Whether the newsletter floating subscribe button is enabled', 'jetpack_subscriptions_subscribe_post_end_enabled' => '(bool) Whether the Subscribe block at the end of each post placement is enabled', 'jetpack_subscriptions_login_navigation_enabled' => '(bool) Whether the Subscriber Login block navigation placement is enabled', 'jetpack_subscriptions_subscribe_navigation_enabled' => '(Bool) Whether the Subscribe block navigation placement is enabled', - 'wpcom_ai_site_prompt' => '(string) User input in the AI site prompt', - 'jetpack_waf_automatic_rules' => '(bool) Whether the WAF should enforce automatic firewall rules', - 'jetpack_waf_ip_allow_list' => '(string) List of IP addresses to always allow', - 'jetpack_waf_ip_allow_list_enabled' => '(bool) Whether the IP allow list is enabled', - 'jetpack_waf_ip_block_list' => '(string) List of IP addresses the WAF should always block', - 'jetpack_waf_ip_block_list_enabled' => '(bool) Whether the IP block list is enabled', - 'jetpack_waf_share_data' => '(bool) Whether the WAF should share basic data with Jetpack', - 'jetpack_waf_share_debug_data' => '(bool) Whether the WAF should share debug data with Jetpack', + 'wpcom_ai_site_prompt' => '(string) User input in the AI site prompt', + 'jetpack_waf_automatic_rules' => '(bool) Whether the WAF should enforce automatic firewall rules', + 'jetpack_waf_ip_allow_list' => '(string) List of IP addresses to always allow', + 'jetpack_waf_ip_allow_list_enabled' => '(bool) Whether the IP allow list is enabled', + 'jetpack_waf_ip_block_list' => '(string) List of IP addresses the WAF should always block', + 'jetpack_waf_ip_block_list_enabled' => '(bool) Whether the IP block list is enabled', + 'jetpack_waf_share_data' => '(bool) Whether the WAF should share basic data with Jetpack', + 'jetpack_waf_share_debug_data' => '(bool) Whether the WAF should share debug data with Jetpack', 'jetpack_waf_automatic_rules_last_updated_timestamp' => '(int) Timestamp of the last time the automatic rules were updated', ), @@ -469,6 +470,7 @@ function ( $newsletter_category ) { 'wpcom_newsletter_categories_enabled' => (bool) get_option( 'wpcom_newsletter_categories_enabled' ), 'sm_enabled' => (bool) get_option( 'sm_enabled' ), 'jetpack_subscribe_overlay_enabled' => (bool) get_option( 'jetpack_subscribe_overlay_enabled' ), + 'jetpack_subscribe_floating_button_enabled' => (bool) get_option( 'jetpack_subscribe_floating_button_enabled' ), 'jetpack_subscriptions_subscribe_post_end_enabled' => (bool) get_option( 'jetpack_subscriptions_subscribe_post_end_enabled' ), 'jetpack_subscriptions_login_navigation_enabled' => (bool) get_option( 'jetpack_subscriptions_login_navigation_enabled' ), 'jetpack_subscriptions_subscribe_navigation_enabled' => (bool) get_option( 'jetpack_subscriptions_subscribe_navigation_enabled' ), @@ -1092,6 +1094,11 @@ function ( $category_id ) { $updated[ $key ] = (int) (bool) $value; break; + case 'jetpack_subscribe_floating_button_enabled': + update_option( 'jetpack_subscribe_floating_button_enabled', (int) (bool) $value ); + $updated[ $key ] = (int) (bool) $value; + break; + case 'jetpack_subscriptions_subscribe_post_end_enabled': update_option( 'jetpack_subscriptions_subscribe_post_end_enabled', (int) (bool) $value ); $updated[ $key ] = (int) (bool) $value; diff --git a/projects/plugins/jetpack/json-endpoints/class.wpcom-json-api-site-settings-v1-4-endpoint.php b/projects/plugins/jetpack/json-endpoints/class.wpcom-json-api-site-settings-v1-4-endpoint.php index 9c6d1cdd4506b..bb0da75ecd15c 100644 --- a/projects/plugins/jetpack/json-endpoints/class.wpcom-json-api-site-settings-v1-4-endpoint.php +++ b/projects/plugins/jetpack/json-endpoints/class.wpcom-json-api-site-settings-v1-4-endpoint.php @@ -35,117 +35,118 @@ ), 'request_format' => array( - 'migration_source_site_domain' => '(string) The source site URL, from the migration flow', - 'in_site_migration_flow' => '(string) Whether the site is currently in the Site Migration signup flow.', - 'blogname' => '(string) Blog name', - 'blogdescription' => '(string) Blog description', - 'default_pingback_flag' => '(bool) Notify blogs linked from article?', - 'default_ping_status' => '(bool) Allow link notifications from other blogs?', - 'default_comment_status' => '(bool) Allow comments on new articles?', - 'blog_public' => '(string) Site visibility; -1: private, 0: discourage search engines, 1: allow search engines', - 'wpcom_data_sharing_opt_out' => '(bool) Did the site opt out of public content sharing with third parties and research partners?', - 'jetpack_sync_non_public_post_stati' => '(bool) allow sync of post and pages with non-public posts stati', - 'jetpack_relatedposts_enabled' => '(bool) Enable related posts?', - 'jetpack_relatedposts_show_context' => '(bool) Show post\'s tags and category in related posts?', - 'jetpack_relatedposts_show_date' => '(bool) Show date in related posts?', - 'jetpack_relatedposts_show_headline' => '(bool) Show headline in related posts?', - 'jetpack_relatedposts_show_thumbnails' => '(bool) Show thumbnails in related posts?', - 'instant_search_enabled' => '(bool) Enable the new Jetpack Instant Search interface', - 'jetpack_search_enabled' => '(bool) Enable Jetpack Search', - 'jetpack_search_supported' => '(bool) Jetpack Search supported', - 'jetpack_protect_whitelist' => '(array) List of IP addresses to always allow', - 'infinite_scroll' => '(bool) Support infinite scroll of posts?', - 'default_category' => '(int) Default post category', - 'default_post_format' => '(string) Default post format', - 'require_name_email' => '(bool) Require comment authors to fill out name and email?', - 'comment_registration' => '(bool) Require users to be registered and logged in to comment?', - 'close_comments_for_old_posts' => '(bool) Automatically close comments on old posts?', - 'close_comments_days_old' => '(int) Age at which to close comments', - 'thread_comments' => '(bool) Enable threaded comments?', - 'thread_comments_depth' => '(int) Depth to thread comments', - 'page_comments' => '(bool) Break comments into pages?', - 'comments_per_page' => '(int) Number of comments to display per page', - 'default_comments_page' => '(string) newest|oldest Which page of comments to display first', - 'comment_order' => '(string) asc|desc Order to display comments within page', - 'comments_notify' => '(bool) Email me when someone comments?', - 'moderation_notify' => '(bool) Email me when a comment is helf for moderation?', - 'social_notifications_like' => '(bool) Email me when someone likes my post?', - 'social_notifications_reblog' => '(bool) Email me when someone reblogs my post?', - 'social_notifications_subscribe' => '(bool) Email me when someone subscribes to my blog?', - 'comment_moderation' => '(bool) Moderate comments for manual approval?', - 'comment_previously_approved' => '(bool) Moderate comments unless author has a previously-approved comment?', - 'comment_max_links' => '(int) Moderate comments that contain X or more links', - 'moderation_keys' => '(string) Words or phrases that trigger comment moderation, one per line', - 'disallowed_keys' => '(string) Words or phrases that mark comment spam, one per line', - 'lang_id' => '(int) ID for language blog is written in', - 'locale' => '(string) locale code for language blog is written in', - 'site_vertical_id' => '(string) The site vertical ID', - 'wga' => '(array) Google Analytics Settings', - 'jetpack_cloudflare_analytics' => '(array) Cloudflare Analytics Settings', - 'disabled_likes' => '(bool) Are likes globally disabled (they can still be turned on per post)?', - 'disabled_reblogs' => '(bool) Are reblogs disabled on posts?', - 'jetpack_comment_likes_enabled' => '(bool) Are comment likes enabled for all comments?', - 'sharing_button_style' => '(string) Style to use for sharing buttons (icon-text, icon, text, or official)', - 'sharing_label' => '(string) Label to use for sharing buttons, e.g. "Share this:"', - 'sharing_show' => '(string|array:string) Post type or array of types where sharing buttons are to be displayed', - 'sharing_open_links' => '(string) Link target for sharing buttons (same or new)', - 'twitter_via' => '(string) Twitter username to include in tweets when people share using the Twitter button', - 'jetpack-twitter-cards-site-tag' => '(string) The Twitter username of the owner of the site\'s domain.', - 'eventbrite_api_token' => '(int) The Keyring token ID for an Eventbrite token to associate with the site', - 'timezone_string' => '(string) PHP-compatible timezone string like \'UTC-5\'', - 'gmt_offset' => '(int) Site offset from UTC in hours', - 'date_format' => '(string) PHP Date-compatible date format', - 'time_format' => '(string) PHP Date-compatible time format', - 'start_of_week' => '(int) Starting day of week (0 = Sunday, 6 = Saturday)', - 'woocommerce_onboarding_profile' => '(array) woocommerce_onboarding_profile', - 'woocommerce_store_address' => '(string) woocommerce_store_address option', - 'woocommerce_store_address_2' => '(string) woocommerce_store_address_2 option', - 'woocommerce_store_city' => '(string) woocommerce_store_city option', - 'woocommerce_default_country' => '(string) woocommerce_default_country option', - 'woocommerce_store_postcode' => '(string) woocommerce_store_postcode option', - 'jetpack_testimonial' => '(bool) Whether testimonial custom post type is enabled for the site', - 'jetpack_testimonial_posts_per_page' => '(int) Number of testimonials to show per page', - 'jetpack_portfolio' => '(bool) Whether portfolio custom post type is enabled for the site', - 'jetpack_portfolio_posts_per_page' => '(int) Number of portfolio projects to show per page', - Jetpack_SEO_Utils::FRONT_PAGE_META_OPTION => '(string) The SEO meta description for the site.', - Jetpack_SEO_Titles::TITLE_FORMATS_OPTION => '(array) SEO meta title formats. Allowed keys: front_page, posts, pages, groups, archives', - 'verification_services_codes' => '(array) Website verification codes. Allowed keys: google, pinterest, bing, yandex, facebook', - 'podcasting_archive' => '(string) The post category, if any, used for publishing podcasts', - 'site_icon' => '(int) Media attachment ID to use as site icon. Set to zero or an otherwise empty value to clear', - 'api_cache' => '(bool) Turn on/off the Jetpack JSON API cache', - 'posts_per_page' => '(int) Number of posts to show on blog pages', - 'posts_per_rss' => '(int) Number of posts to show in the RSS feed', - 'rss_use_excerpt' => '(bool) Whether the RSS feed will use post excerpts', - 'wpcom_publish_posts_with_markdown' => '(bool) Whether markdown is enabled for posts', - 'wpcom_publish_comments_with_markdown' => '(bool) Whether markdown is enabled for comments', - 'launchpad_screen' => '(string) Whether or not launchpad is presented and what size it will be', - 'wpcom_featured_image_in_email' => '(bool) Whether the Featured image is displayed in the New Post email template or not', - 'jetpack_gravatar_in_email' => '(bool) Whether to show author avatar in the email byline', - 'jetpack_author_in_email' => '(bool) Whether to show author display name in the email byline', - 'jetpack_post_date_in_email' => '(bool) Whether to show date in the email byline', - 'wpcom_newsletter_categories' => '(array) Array of post category ids that are marked as newsletter categories', - 'wpcom_newsletter_categories_enabled' => '(bool) Whether the newsletter categories are enabled or not', - 'sm_enabled' => '(bool) Whether the newsletter Subscribe Modal is enabled or not', - 'jetpack_subscribe_overlay_enabled' => '(bool) Whether the newsletter Subscribe Overlay is enabled or not', + 'migration_source_site_domain' => '(string) The source site URL, from the migration flow', + 'in_site_migration_flow' => '(string) Whether the site is currently in the Site Migration signup flow.', + 'blogname' => '(string) Blog name', + 'blogdescription' => '(string) Blog description', + 'default_pingback_flag' => '(bool) Notify blogs linked from article?', + 'default_ping_status' => '(bool) Allow link notifications from other blogs?', + 'default_comment_status' => '(bool) Allow comments on new articles?', + 'blog_public' => '(string) Site visibility; -1: private, 0: discourage search engines, 1: allow search engines', + 'wpcom_data_sharing_opt_out' => '(bool) Did the site opt out of public content sharing with third parties and research partners?', + 'jetpack_sync_non_public_post_stati' => '(bool) allow sync of post and pages with non-public posts stati', + 'jetpack_relatedposts_enabled' => '(bool) Enable related posts?', + 'jetpack_relatedposts_show_context' => '(bool) Show post\'s tags and category in related posts?', + 'jetpack_relatedposts_show_date' => '(bool) Show date in related posts?', + 'jetpack_relatedposts_show_headline' => '(bool) Show headline in related posts?', + 'jetpack_relatedposts_show_thumbnails' => '(bool) Show thumbnails in related posts?', + 'instant_search_enabled' => '(bool) Enable the new Jetpack Instant Search interface', + 'jetpack_search_enabled' => '(bool) Enable Jetpack Search', + 'jetpack_search_supported' => '(bool) Jetpack Search supported', + 'jetpack_protect_whitelist' => '(array) List of IP addresses to always allow', + 'infinite_scroll' => '(bool) Support infinite scroll of posts?', + 'default_category' => '(int) Default post category', + 'default_post_format' => '(string) Default post format', + 'require_name_email' => '(bool) Require comment authors to fill out name and email?', + 'comment_registration' => '(bool) Require users to be registered and logged in to comment?', + 'close_comments_for_old_posts' => '(bool) Automatically close comments on old posts?', + 'close_comments_days_old' => '(int) Age at which to close comments', + 'thread_comments' => '(bool) Enable threaded comments?', + 'thread_comments_depth' => '(int) Depth to thread comments', + 'page_comments' => '(bool) Break comments into pages?', + 'comments_per_page' => '(int) Number of comments to display per page', + 'default_comments_page' => '(string) newest|oldest Which page of comments to display first', + 'comment_order' => '(string) asc|desc Order to display comments within page', + 'comments_notify' => '(bool) Email me when someone comments?', + 'moderation_notify' => '(bool) Email me when a comment is helf for moderation?', + 'social_notifications_like' => '(bool) Email me when someone likes my post?', + 'social_notifications_reblog' => '(bool) Email me when someone reblogs my post?', + 'social_notifications_subscribe' => '(bool) Email me when someone subscribes to my blog?', + 'comment_moderation' => '(bool) Moderate comments for manual approval?', + 'comment_previously_approved' => '(bool) Moderate comments unless author has a previously-approved comment?', + 'comment_max_links' => '(int) Moderate comments that contain X or more links', + 'moderation_keys' => '(string) Words or phrases that trigger comment moderation, one per line', + 'disallowed_keys' => '(string) Words or phrases that mark comment spam, one per line', + 'lang_id' => '(int) ID for language blog is written in', + 'locale' => '(string) locale code for language blog is written in', + 'site_vertical_id' => '(string) The site vertical ID', + 'wga' => '(array) Google Analytics Settings', + 'jetpack_cloudflare_analytics' => '(array) Cloudflare Analytics Settings', + 'disabled_likes' => '(bool) Are likes globally disabled (they can still be turned on per post)?', + 'disabled_reblogs' => '(bool) Are reblogs disabled on posts?', + 'jetpack_comment_likes_enabled' => '(bool) Are comment likes enabled for all comments?', + 'sharing_button_style' => '(string) Style to use for sharing buttons (icon-text, icon, text, or official)', + 'sharing_label' => '(string) Label to use for sharing buttons, e.g. "Share this:"', + 'sharing_show' => '(string|array:string) Post type or array of types where sharing buttons are to be displayed', + 'sharing_open_links' => '(string) Link target for sharing buttons (same or new)', + 'twitter_via' => '(string) Twitter username to include in tweets when people share using the Twitter button', + 'jetpack-twitter-cards-site-tag' => '(string) The Twitter username of the owner of the site\'s domain.', + 'eventbrite_api_token' => '(int) The Keyring token ID for an Eventbrite token to associate with the site', + 'timezone_string' => '(string) PHP-compatible timezone string like \'UTC-5\'', + 'gmt_offset' => '(int) Site offset from UTC in hours', + 'date_format' => '(string) PHP Date-compatible date format', + 'time_format' => '(string) PHP Date-compatible time format', + 'start_of_week' => '(int) Starting day of week (0 = Sunday, 6 = Saturday)', + 'woocommerce_onboarding_profile' => '(array) woocommerce_onboarding_profile', + 'woocommerce_store_address' => '(string) woocommerce_store_address option', + 'woocommerce_store_address_2' => '(string) woocommerce_store_address_2 option', + 'woocommerce_store_city' => '(string) woocommerce_store_city option', + 'woocommerce_default_country' => '(string) woocommerce_default_country option', + 'woocommerce_store_postcode' => '(string) woocommerce_store_postcode option', + 'jetpack_testimonial' => '(bool) Whether testimonial custom post type is enabled for the site', + 'jetpack_testimonial_posts_per_page' => '(int) Number of testimonials to show per page', + 'jetpack_portfolio' => '(bool) Whether portfolio custom post type is enabled for the site', + 'jetpack_portfolio_posts_per_page' => '(int) Number of portfolio projects to show per page', + Jetpack_SEO_Utils::FRONT_PAGE_META_OPTION => '(string) The SEO meta description for the site.', + Jetpack_SEO_Titles::TITLE_FORMATS_OPTION => '(array) SEO meta title formats. Allowed keys: front_page, posts, pages, groups, archives', + 'verification_services_codes' => '(array) Website verification codes. Allowed keys: google, pinterest, bing, yandex, facebook', + 'podcasting_archive' => '(string) The post category, if any, used for publishing podcasts', + 'site_icon' => '(int) Media attachment ID to use as site icon. Set to zero or an otherwise empty value to clear', + 'api_cache' => '(bool) Turn on/off the Jetpack JSON API cache', + 'posts_per_page' => '(int) Number of posts to show on blog pages', + 'posts_per_rss' => '(int) Number of posts to show in the RSS feed', + 'rss_use_excerpt' => '(bool) Whether the RSS feed will use post excerpts', + 'wpcom_publish_posts_with_markdown' => '(bool) Whether markdown is enabled for posts', + 'wpcom_publish_comments_with_markdown' => '(bool) Whether markdown is enabled for comments', + 'launchpad_screen' => '(string) Whether or not launchpad is presented and what size it will be', + 'wpcom_featured_image_in_email' => '(bool) Whether the Featured image is displayed in the New Post email template or not', + 'jetpack_gravatar_in_email' => '(bool) Whether to show author avatar in the email byline', + 'jetpack_author_in_email' => '(bool) Whether to show author display name in the email byline', + 'jetpack_post_date_in_email' => '(bool) Whether to show date in the email byline', + 'wpcom_newsletter_categories' => '(array) Array of post category ids that are marked as newsletter categories', + 'wpcom_newsletter_categories_enabled' => '(bool) Whether the newsletter categories are enabled or not', + 'sm_enabled' => '(bool) Whether the newsletter Subscribe Modal is enabled or not', + 'jetpack_subscribe_overlay_enabled' => '(bool) Whether the newsletter Subscribe Overlay is enabled or not', + 'jetpack_subscribe_floating_button_enabled' => '(bool) Whether the newsletter floating subscribe button is enabled or not', 'jetpack_subscriptions_subscribe_post_end_enabled' => '(bool) Whether adding Subscribe block at the end of each post is enabled or not', 'jetpack_subscriptions_login_navigation_enabled' => '(bool) Whether the Subscriber Login block navigation placement is enabled or not', 'jetpack_subscriptions_subscribe_navigation_enabled' => '(bool) Whether the Subscribe block navigation placement is enabled or not', - 'wpcom_gifting_subscription' => '(bool) Whether gifting is enabled for non auto-renew sites', - 'wpcom_reader_views_enabled' => '(bool) Whether showing post views in WordPress.com Reader is enabled for the site', - 'wpcom_subscription_emails_use_excerpt' => '(bool) Whether site subscription emails (e.g. New Post email notification) will use post excerpts', - 'jetpack_subscriptions_reply_to' => '(string) The reply to email behaviour for newsletter emails', - 'jetpack_subscriptions_from_name' => '(string) The from name for newsletter emails', - 'show_on_front' => '(string) Whether homepage should display related posts or a static page. The expected value is \'posts\' or \'page\'.', - 'page_on_front' => '(string) The page ID of the page to use as the site\'s homepage. It will apply only if \'show_on_front\' is set to \'page\'.', - 'page_for_posts' => '(string) The page ID of the page to use as the site\'s posts page. It will apply only if \'show_on_front\' is set to \'page\'.', - 'subscription_options' => '(array) Array of three options used in subscription email templates: \'invitation\', \'welcome\' and \'comment_follow\' strings.', - 'jetpack_verbum_subscription_modal' => '(bool) Whether Subscription modal is enabled in Verbum comments', - 'wpcom_ai_site_prompt' => '(string) User input in the AI site prompt', - 'enable_verbum_commenting' => '(bool) Whether Verbum commenting is enabled', - 'enable_blocks_comments' => '(bool) Whether blocks comments are enabled', - 'highlander_comment_form_prompt' => '(string) The prompt for the comment form', - 'jetpack_comment_form_color_scheme' => '(string) The color scheme for the comment form', - 'is_fully_managed_agency_site' => '(bool) Whether the site is a fully managed agency site', + 'wpcom_gifting_subscription' => '(bool) Whether gifting is enabled for non auto-renew sites', + 'wpcom_reader_views_enabled' => '(bool) Whether showing post views in WordPress.com Reader is enabled for the site', + 'wpcom_subscription_emails_use_excerpt' => '(bool) Whether site subscription emails (e.g. New Post email notification) will use post excerpts', + 'jetpack_subscriptions_reply_to' => '(string) The reply to email behaviour for newsletter emails', + 'jetpack_subscriptions_from_name' => '(string) The from name for newsletter emails', + 'show_on_front' => '(string) Whether homepage should display related posts or a static page. The expected value is \'posts\' or \'page\'.', + 'page_on_front' => '(string) The page ID of the page to use as the site\'s homepage. It will apply only if \'show_on_front\' is set to \'page\'.', + 'page_for_posts' => '(string) The page ID of the page to use as the site\'s posts page. It will apply only if \'show_on_front\' is set to \'page\'.', + 'subscription_options' => '(array) Array of three options used in subscription email templates: \'invitation\', \'welcome\' and \'comment_follow\' strings.', + 'jetpack_verbum_subscription_modal' => '(bool) Whether Subscription modal is enabled in Verbum comments', + 'wpcom_ai_site_prompt' => '(string) User input in the AI site prompt', + 'enable_verbum_commenting' => '(bool) Whether Verbum commenting is enabled', + 'enable_blocks_comments' => '(bool) Whether blocks comments are enabled', + 'highlander_comment_form_prompt' => '(string) The prompt for the comment form', + 'jetpack_comment_form_color_scheme' => '(string) The color scheme for the comment form', + 'is_fully_managed_agency_site' => '(bool) Whether the site is a fully managed agency site', ), 'response_format' => array( diff --git a/projects/plugins/jetpack/json-endpoints/class.wpcom-json-api-upload-media-v1-1-endpoint.php b/projects/plugins/jetpack/json-endpoints/class.wpcom-json-api-upload-media-v1-1-endpoint.php index 2dd816c37e249..5ea49e7d89ba6 100644 --- a/projects/plugins/jetpack/json-endpoints/class.wpcom-json-api-upload-media-v1-1-endpoint.php +++ b/projects/plugins/jetpack/json-endpoints/class.wpcom-json-api-upload-media-v1-1-endpoint.php @@ -93,7 +93,7 @@ public function callback( $path = '', $blog_id = 0 ) { // We're splitting out videos for Jetpack sites. foreach ( $media_files as $media_item ) { - if ( preg_match( '@^video/@', $media_item['type'] ) && $is_jetpack_site ) { + if ( isset( $media_item['type'] ) && preg_match( '@^video/@', $media_item['type'] ) && $is_jetpack_site ) { if ( defined( 'IS_WPCOM' ) && IS_WPCOM && defined( 'VIDEOPRESS_JETPACK_VIDEO_ENABLED' ) && VIDEOPRESS_JETPACK_VIDEO_ENABLED ) { diff --git a/projects/plugins/jetpack/modules/stats.php b/projects/plugins/jetpack/modules/stats.php index cf12fe07c5ee9..224ba4a177d89 100644 --- a/projects/plugins/jetpack/modules/stats.php +++ b/projects/plugins/jetpack/modules/stats.php @@ -54,7 +54,10 @@ function stats_load() { Jetpack::enable_module_configurable( __FILE__ ); - add_action( 'wp_head', 'stats_admin_bar_head', 100 ); + // Only run the callback for those who can see the stats. + if ( is_user_logged_in() && current_user_can( 'view_stats' ) ) { + add_action( 'wp_head', 'stats_admin_bar_head', 100 ); + } add_action( 'jetpack_admin_menu', 'stats_admin_menu' ); diff --git a/projects/plugins/jetpack/modules/subscriptions.php b/projects/plugins/jetpack/modules/subscriptions.php index 87801f8868919..850f474f00c4f 100644 --- a/projects/plugins/jetpack/modules/subscriptions.php +++ b/projects/plugins/jetpack/modules/subscriptions.php @@ -1047,3 +1047,4 @@ public function track_newsletter_category_creation() { require __DIR__ . '/subscriptions/views.php'; require __DIR__ . '/subscriptions/subscribe-modal/class-jetpack-subscribe-modal.php'; require __DIR__ . '/subscriptions/subscribe-overlay/class-jetpack-subscribe-overlay.php'; +require __DIR__ . '/subscriptions/subscribe-floating-button/class-jetpack-subscribe-floating-button.php'; diff --git a/projects/plugins/jetpack/modules/subscriptions/subscribe-floating-button/class-jetpack-subscribe-floating-button.php b/projects/plugins/jetpack/modules/subscriptions/subscribe-floating-button/class-jetpack-subscribe-floating-button.php new file mode 100644 index 0000000000000..09bb8ec5de85a --- /dev/null +++ b/projects/plugins/jetpack/modules/subscriptions/subscribe-floating-button/class-jetpack-subscribe-floating-button.php @@ -0,0 +1,196 @@ +get_template(); + } + } + + return $block_template; + } + + /** + * Returns a custom template for the floating Subscribe button. + * + * @return WP_Block_Template + */ + public function get_template() { + $template = new WP_Block_Template(); + $template->theme = get_stylesheet(); + $template->slug = self::BLOCK_TEMPLATE_PART_SLUG; + $template->id = self::get_block_template_part_id(); + $template->area = 'uncategorized'; + $template->content = $this->get_floating_subscribe_button_template_content(); + $template->source = 'plugin'; + $template->type = 'wp_template_part'; + $template->title = __( 'Jetpack Subscribe floating button', 'jetpack' ); + $template->status = 'publish'; + $template->has_theme_file = false; + $template->is_custom = true; + $template->description = __( 'A floating subscribe button that shows up when someone visits your site.', 'jetpack' ); + + return $template; + } + + /** + * Returns the initial content of the floating Subscribe button template. + * This can then be edited by the user. + * + * @return string + */ + public function get_floating_subscribe_button_template_content() { + $block_name = esc_attr__( 'Floating subscribe button', 'jetpack' ); + + return ''; + } + + /** + * Enqueues styles. + * + * @return void + */ + public function enqueue_assets() { + if ( $this->should_user_see_floating_button() ) { + wp_enqueue_style( 'subscribe-floating-button-css', plugins_url( 'subscribe-floating-button.css', __FILE__ ), array(), JETPACK__VERSION ); + + // Disables WP.com action bar as the features collide/overlap + add_filter( 'wpcom_disable_logged_out_follow', '__return_true', 10, 1 ); + } + } + + /** + * Adds floating Subscribe button HTML wrapper + * + * @return void + */ + public function add_subscribe_floating_button_to_frontend() { + if ( $this->should_user_see_floating_button() ) { ?> +
+ +
+ false, 'sm_enabled' => false, 'jetpack_subscribe_overlay_enabled' => false, + 'jetpack_subscribe_floating_button_enabled' => false, 'jetpack_subscriptions_subscribe_post_end_enabled' => false, 'jetpack_subscriptions_login_navigation_enabled' => false, 'jetpack_subscriptions_subscribe_navigation_enabled' => false, @@ -277,7 +278,6 @@ public function test_sync_default_options() { 'jetpack_waf_share_data' => true, 'jetpack_waf_share_debug_data' => false, 'jetpack_waf_automatic_rules_last_updated_timestamp' => 0, - 'woocommerce_analytics_first_activation' => false, ); $theme_mod_key = 'theme_mods_' . get_option( 'stylesheet' ); diff --git a/projects/plugins/jetpack/to-test.md b/projects/plugins/jetpack/to-test.md index 17612f968e23d..0b898396b9eb5 100644 --- a/projects/plugins/jetpack/to-test.md +++ b/projects/plugins/jetpack/to-test.md @@ -10,9 +10,33 @@ - Or add the following to something like a code snippet plugin: `add_filter( 'jetpack_blocks_variation', function () { return 'beta'; } );` - To test Breve further in the document please enable the feature with the following snippet: `add_filter( 'breve_enabled', '__return_true' );` -### Your Feature +### AI Logo Generator -Add testing instructions below. +On top of the already available AI Logo generator, we've now added a styles dropdown to allow more control for the user without depending entirely on the provided prompt. + +The logo generator is not available for free users, test with a plan or subscription. Also, it's currenlty available for a12s (and will soon be open to public), but if you need to test with another account and have access to a sandbox, you can add a filter to enable the styles on your 0-sandbox.php file: `add_filter( 'jetpack_ai_logo_style_selector_enabled', '__return_true' );` + +- Load the editor and add a Logo block. +- On the network tab you should see a request to `ai-assistant-feature` + - If using an a11n account (or focing the filter to `true`), the response should include `featuresControl['logo-generator'].styles` as a collection of style objects. + - If NOT using an a11n account, the `styles` property should be an empty array. +``` +{ + ... + featuresControl: { + 'logo-generator': { + enabled: true, + styles: [ COLLECTION OF SYLES HERE ] + } + } +} +``` +- Use the block's AI toolbar button to open the Logo generator modal, you should see a style dropdown on the top-right corner +- Feel free to play with the styles to achieve different results +- Confirm that using style "Auto" will try to guess the style based on the prompt (AI query request) and set the style prior to sending the image generation request +- If possible, try different combinations of plans and cases: + - use `add_filter( 'jetpack_ai_tier_licensed_quantity', function() { return 0 | 100 | 1; } );` filter to mock free/tier100/unlimited plans + - sandbox the API, but then don't connect to sandbox to mock a disconnected situation ### And More!