Model: Make dwell delay part of model and registration

Dwell delay varies between popup type so should be part of the
definition. Since this is needed by reference tooltips we should
make this part of the Page preview model. This will allow us to
separate concerns of the architecture and reference  tooltips
for better maintenance between WMDE and web team.

Bug: T326692
Change-Id: Ia021c8b90fd69d70c4b33744520bb963a65db036
This commit is contained in:
Jon Robson 2023-03-22 08:54:25 -07:00
parent 970e7112a5
commit 9aa07d0809
9 changed files with 63 additions and 47 deletions

View file

@ -71,7 +71,7 @@
"bundlesize": [
{
"path": "resources/dist/index.js",
"maxSize": "14.6kB"
"maxSize": "14.7kB"
}
]
}

Binary file not shown.

Binary file not shown.

View file

@ -4,31 +4,8 @@
import types from './actionTypes';
import wait from './wait';
import { createNullModel, previewTypes } from './preview/model';
const
// See the following for context around this value.
//
// * https://phabricator.wikimedia.org/T161284
// * https://phabricator.wikimedia.org/T70861#3129780
FETCH_START_DELAY = 150, // ms.
// The minimum time a preview must be open before we judge it
// has been seen.
// See https://phabricator.wikimedia.org/T184793
PREVIEW_SEEN_DURATION = 1000, // ms
// The delay after which a FETCH_COMPLETE action should be dispatched.
//
// If the API endpoint responds faster than 350 ms (or, say, the API
// response is served from the UA's cache), then we introduce a delay of
// 350 ms - t to make the preview delay consistent to the user. The total
// delay from start to finish is 500 ms.
FETCH_COMPLETE_TARGET_DELAY = 350 + FETCH_START_DELAY, // ms.
FETCH_DELAY_REFERENCE_TYPE = 150, // ms.
ABANDON_END_DELAY = 300; // ms.
import { createNullModel, previewTypes, getDwellDelay } from './preview/model';
import { FETCH_START_DELAY, PREVIEW_SEEN_DURATION, ABANDON_END_DELAY } from './constants';
/**
* Mixes in timing information to an action.
@ -95,23 +72,6 @@ export function boot(
};
}
/**
* Determines the delay before showing the preview when dwelling a link.
*
* @param {string} type
* @return {number}
*/
function getDwellDelay( type ) {
switch ( type ) {
case previewTypes.TYPE_PAGE:
return FETCH_COMPLETE_TARGET_DELAY - FETCH_START_DELAY;
case previewTypes.TYPE_REFERENCE:
return FETCH_DELAY_REFERENCE_TYPE;
default:
return 0;
}
}
/**
* Represents Page Previews fetching data via the gateway.
*

View file

@ -2,6 +2,29 @@ import bracketedPixelRatio from './bracketedPixelRatio';
const bpr = bracketedPixelRatio();
// See the following for context around this value.
//
// * https://phabricator.wikimedia.org/T161284
// * https://phabricator.wikimedia.org/T70861#3129780
export const FETCH_START_DELAY = 150; // ms.
// The delay after which a FETCH_COMPLETE action should be dispatched.
//
// If the API endpoint responds faster than 350 ms (or, say, the API
// response is served from the UA's cache), then we introduce a delay of
// 350 ms - t to make the preview delay consistent to the user. The total
// delay from start to finish is 500 ms.
export const FETCH_COMPLETE_TARGET_DELAY = 350 + FETCH_START_DELAY; // ms.
// The minimum time a preview must be open before we judge it
// has been seen.
// See https://phabricator.wikimedia.org/T184793
export const PREVIEW_SEEN_DURATION = 1000; // ms
export const ABANDON_END_DELAY = 300;
//
// Reference previews specific config
//
export const FETCH_DELAY_REFERENCE_TYPE = 150; // ms.
export default {
BRACKETED_DEVICE_PIXEL_RATIO: bpr,
// See https://phabricator.wikimedia.org/T272169: requesting a larger thumbnail to avoid bluriness

View file

@ -30,6 +30,7 @@ import isReferencePreviewsEnabled from './isReferencePreviewsEnabled';
import setUserConfigFlags from './setUserConfigFlags';
import { registerGatewayForPreviewType, getGatewayForPreviewType } from './gateway';
import { initReferencePreviewsInstrumentation } from './instrumentation/referencePreviews';
import { FETCH_START_DELAY, FETCH_COMPLETE_TARGET_DELAY, FETCH_DELAY_REFERENCE_TYPE } from './constants';
const EXCLUDED_LINK_SELECTORS = [
'.extiw',
@ -245,6 +246,7 @@ function handleDOMEventIfEligible( handler ) {
mw.popups.register( {
type: previewTypes.TYPE_PAGE,
selector: `#mw-content-text a[href][title]:not(${excludedLinksSelector})`,
delay: FETCH_COMPLETE_TARGET_DELAY - FETCH_START_DELAY,
gateway: pagePreviewGateway,
renderFn: createPagePreview,
subTypes: [
@ -260,6 +262,7 @@ function handleDOMEventIfEligible( handler ) {
mw.popups.register( {
type: previewTypes.TYPE_REFERENCE,
selector: '#mw-content-text .reference a[ href*="#" ]',
delay: FETCH_DELAY_REFERENCE_TYPE,
gateway: referenceGateway,
renderFn: createReferencePreview,
init: () => {

View file

@ -38,6 +38,8 @@ export default function createMwPopups( store, registerModel, registerPreviewUI,
* @property {function(ext.popups.PreviewModel): ext.popups.Preview}[renderFn] How the custom preview type will render the preview.
* If not provided default renderer is used.
* @property {PopupSubtype[]} subTypes this is for registering types that are subsets of the current type e.g. share the same selector.
* @property {number} [delay] optional delay between hovering and displaying preview.
* If not defined, delay will be zero.
*/
/**
* Register a custom preview type.
@ -57,13 +59,13 @@ export default function createMwPopups( store, registerModel, registerPreviewUI,
* @param {PopupModule} module
*/
register: function ( module ) {
const { type, selector, gateway, renderFn, subTypes, init } = module;
const { type, selector, gateway, renderFn, subTypes, delay, init } = module;
if ( !type || !selector || !gateway ) {
throw new Error(
`Registration of Popups custom preview type "${type}" failed: You must specify a type, a selector, and a gateway.`
);
}
registerModel( type, selector );
registerModel( type, selector, delay );
registerGatewayForPreviewType( type, gateway );
registerPreviewUI( type, renderFn );
if ( subTypes ) {

View file

@ -203,19 +203,46 @@ function getPagePreviewType( type, processedExtract ) {
const selectors = [];
const dwellDelay = {};
/**
* Determines the delay before showing the preview when dwelling a link.
*
* @param {string} type
* @return {number}
*/
export function getDwellDelay( type ) {
return dwellDelay[ type ] || 0;
}
/***
* Set the delay before showing the preview when dwelling a link.
*
* @param {string} type
* @param {number} delay
*/
export function setDwellTime( type, delay ) {
dwellDelay[ type ] = delay;
}
/**
* Allows extensions to register their own page previews.
*
* @stable
* @param {string} type
* @param {string} selector A valid CSS selector to associate preview with
* @param {number} [delay] optional delay between hovering and displaying preview.
* If not defined, delay will be zero.
*/
export function registerModel( type, selector ) {
export function registerModel( type, selector, delay ) {
selectors.push( selector );
registeredPreviewTypes.push( {
name: type,
selector
} );
if ( delay ) {
setDwellTime( type, delay );
}
}
/**

View file

@ -2,7 +2,7 @@ import { createStubUser, createStubTitle } from './stubs';
import * as actions from '../../src/actions';
import * as WaitModule from '../../src/wait';
import actionTypes from '../../src/actionTypes';
import { previewTypes } from '../../src/preview/model';
import { setDwellTime, previewTypes } from '../../src/preview/model';
const REFERRER = 'https://en.wikipedia.org/wiki/Kitten',
TEST_TITLE = createStubTitle( 0, 'Foo' );
@ -268,6 +268,7 @@ QUnit.module( 'ext.popups/actions#fetch', {
this.token = '1234567890';
// Sugar.
setDwellTime( previewTypes.TYPE_PAGE, 350 );
this.fetch = () => {
return actions.fetch(
this.gateway, this.title, this.el, this.token, previewTypes.TYPE_PAGE