Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Replace design screenshots with mShots in New Onboarding #43428

Merged
merged 17 commits into from
Jan 22, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
48 changes: 22 additions & 26 deletions client/landing/gutenboarding/available-designs.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import { addQueryArgs } from '@wordpress/url';
* Internal dependencies
*/
import { isEnabled } from '../../config';
import { mshotsUrl } from './components/mshots-image';
import type { Design } from './stores/onboard/types';
const availableDesignsConfig = require( './available-designs-config.json' );

Expand All @@ -26,45 +27,40 @@ function getCanUseWebP() {
return false;
}

const canUseWebP = getCanUseWebP();

export const getDesignImageUrl = ( design: Design ) => {
// We temporarily show pre-generated screenshots until we can generate tall versions dynamically using mshots.
// See `bin/generate-gutenboarding-design-thumbnails.js` for generating screenshots.
// https://github.com/Automattic/mShots/issues/16
// https://github.com/Automattic/wp-calypso/issues/40564
if ( ! isEnabled( 'gutenboarding/mshot-preview' ) ) {
// When we update the static images, bump the version for cache busting
return `/calypso/images/design-screenshots/${ design.slug }_${ design.template }_${
design.theme
}.${ canUseWebP ? 'webp' : 'jpg' }?v=3`;
}
export const getDesignUrl = ( design: Design, locale: string ): string => {
const theme = encodeURIComponent( design.theme );
const template = encodeURIComponent( design.template );

const mshotsUrl = 'https://s.wordpress.com/mshots/v1/';
const designsEndpoint = 'https://public-api.wordpress.com/rest/v1/template/demo/';
const previewUrl = addQueryArgs(
`${ designsEndpoint }${ encodeURIComponent( design.theme ) }/${ encodeURIComponent(
design.template
) }`,
return addQueryArgs(
`https://public-api.wordpress.com/rest/v1/template/demo/${ theme }/${ template }`,
{
font_headings: design.fonts.headings,
font_base: design.fonts.base,
site_title: design.title,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If we exclude site_title, we'd more often have previews generated already instead of needing to generate for each customer separately.

That said, if it works, would be really cool to include it in thumbnails. 😁

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is actually the theme title (maybe it wasn't previously?) I think I'll try using users title tomorrow, see how it goes, prefetching seems to work decently well at the moment.)

Copy link
Member

@simison simison Jan 20, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ahh, gotcha! Users title would be awesome of course — it'll just potentially generate a whole lot more mshots images once this is live to more people, so might be good to give systems heads up?

Also just slower since every image needs to be generated for each user, but good to test how that tradeoff looks like? My preference is on speed.

viewport_height: 700, // todo: this is part of the issue with rockfield, a value of 3072 here fixes the background image
language: locale,
}
);
return mshotsUrl + encodeURIComponent( previewUrl );
};

/**
* Asynchronously load available design images
*/
export function prefetchDesignThumbs() {
const canUseWebP = getCanUseWebP();

export const getDesignImageUrl = ( design: Design ): string => {
return `/calypso/images/design-screenshots/${ design.slug }_${ design.template }_${
design.theme
}.${ canUseWebP ? 'webp' : 'jpg' }?v=3`;
};

// Asynchronously load available design images
export function prefetchDesignThumbs( locale: string ): void {
if ( typeof window !== 'undefined' ) {
getAvailableDesigns().featured.forEach( ( design: Design ) => {
const href = getDesignImageUrl( design );
const href = mshotsUrl( getDesignUrl( design, locale ) );
const link = document.createElement( 'link' );
link.rel = 'prefetch';
link.as = 'image';
link.href = href;
link.crossOrigin = 'anonymous';
document.head.appendChild( link );
} );
}
Expand All @@ -73,7 +69,7 @@ export function prefetchDesignThumbs() {
export function getAvailableDesigns(
includeAlphaDesigns: boolean = isEnabled( 'gutenboarding/alpha-templates' ),
useFseDesigns: boolean = isEnabled( 'gutenboarding/site-editor' )
) {
): AvailableDesigns {
let designs = availableDesigns;

if ( ! includeAlphaDesigns ) {
Expand Down
72 changes: 72 additions & 0 deletions client/landing/gutenboarding/components/mshots-image/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
/**
* External dependencies
*/
import React, { useState } from 'react';
import classnames from 'classnames';
import { addQueryArgs } from '@wordpress/url';

/**
* Style dependencies
*/
import './style.scss';

interface MShotsImageProps {
url: string;
alt: string;
'aria-labelledby': string;
}

const mShotsParams = {
// viewport size (how much of the source page to capture)
vpw: 1200,
vph: 3072,
// size of the resulting image
w: 700,
h: 1800,
};

export function mshotsUrl( url: string, count = 0 ): string {
const mshotsUrl = 'https://s0.wp.com/mshots/v1/';
const mshotsRequest = addQueryArgs( mshotsUrl + encodeURIComponent( url ), {
...mShotsParams,
// this doesn't seem to work:
lsl marked this conversation as resolved.
Show resolved Hide resolved
// requeue: true, // Uncomment this line to force the screenshots to be regenerated
count,
} );
return mshotsRequest;
}

const MShotsImage = ( {
url,
'aria-labelledby': labelledby,
alt,
}: MShotsImageProps ): JSX.Element => {
const [ count, setCount ] = React.useState( 0 );
const [ visible, setVisible ] = useState( false );
return (
<div className="mshots-image__container">
{ ! visible && <div className="mshots-image__loader"></div> }
<img
className={ classnames( 'mshots-image' ) }
style={ { opacity: visible ? 1 : 0 } }
alt={ alt }
aria-labelledby={ labelledby }
src={ mshotsUrl( url, count ) }
onLoad={ ( e ) => {
// Test against mshots h value
if ( e.currentTarget.naturalHeight !== mShotsParams.h ) {
// Only refresh 10 times.
if ( count < 10 ) {
// Triggers a target.src change
setTimeout( () => setCount( count + 1 ), 1000 );
}
} else {
setVisible( true );
}
} }
/>
</div>
);
};

export default MShotsImage;
19 changes: 19 additions & 0 deletions client/landing/gutenboarding/components/mshots-image/style.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
@import '../../mixins.scss';

.mshots-image {
opacity: 0;
transition: 0.3s opacity;
}

.mshots-image__loader {
@include onboarding-placeholder();
position: absolute;
left: 0;
top: 0;
width: 100%;
height: 100%;
}

.mshots-image-visible {
opacity: 1;
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import { Tooltip } from '@wordpress/components';
import { useDispatch, useSelect } from '@wordpress/data';
import { useI18n } from '@automattic/react-i18n';
import { useLocale } from '@automattic/i18n-utils';
import React from 'react';
import { Title, SubTitle, ActionButtons, BackButton } from '@automattic/onboarding';

Expand All @@ -15,10 +16,12 @@ import { STORE_KEY as ONBOARD_STORE } from '../../stores/onboard';
import { useTrackStep } from '../../hooks/use-track-step';
import useStepNavigation from '../../hooks/use-step-navigation';
import Badge from '../../components/badge';
import { getDesignImageUrl } from '../../available-designs';
import MShotsImage from '../../components/mshots-image';
import { getDesignImageUrl, getDesignUrl } from '../../available-designs';
import JetpackLogo from 'calypso/components/jetpack-logo'; // @TODO: extract to @automattic package
import type { Design } from '../../stores/onboard/types';
import { useIsAnchorFm } from '../../path';
import { isEnabled } from 'calypso/config';

/**
* Style dependencies
Expand All @@ -29,6 +32,7 @@ const makeOptionId = ( { slug }: Design ): string => `design-selector__option-na

const DesignSelector: React.FunctionComponent = () => {
const { __ } = useI18n();
const locale = useLocale();
const { goBack, goNext } = useStepNavigation();

const { setSelectedDesign, setFonts } = useDispatch( ONBOARD_STORE );
Expand Down Expand Up @@ -85,11 +89,19 @@ const DesignSelector: React.FunctionComponent = () => {
} }
>
<span className="design-selector__image-frame">
<img
alt=""
aria-labelledby={ makeOptionId( design ) }
src={ getDesignImageUrl( design ) }
/>
{ isEnabled( 'gutenboarding/mshot-preview' ) ? (
<MShotsImage
url={ getDesignUrl( design, locale ) }
aria-labelledby={ makeOptionId( design ) }
alt=""
/>
) : (
<img
alt=""
aria-labelledby={ makeOptionId( design ) }
src={ getDesignImageUrl( design ) }
/>
) }
</span>
<span className="design-selector__option-overlay">
<span id={ makeOptionId( design ) } className="design-selector__option-meta">
Expand Down