Skip to content

Commit 066e84c

Browse files
committed
Improve singletons
1 parent 78c98bc commit 066e84c

File tree

10 files changed

+147
-86
lines changed

10 files changed

+147
-86
lines changed

includes/Renderer/Stories/Renderer.php

+5-6
Original file line numberDiff line numberDiff line change
@@ -374,12 +374,11 @@ class="<?php echo esc_attr( $single_story_classes ); ?>"
374374
class="<?php echo esc_attr( $single_story_classes ); ?>"
375375
data-wp-interactive="web-stories-block"
376376
<?php
377-
echo esc_attr(
378-
wp_interactivity_data_wp_context(
379-
[
380-
'instanceId' => $this->instance_id,
381-
]
382-
)
377+
// phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
378+
echo wp_interactivity_data_wp_context(
379+
[
380+
'instanceId' => $this->instance_id,
381+
]
383382
);
384383
?>
385384
data-wp-on--click="actions.open"

includes/Renderer/Story/Singleton.php

+24-4
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@
3232
use Google\Web_Stories\Assets;
3333
use Google\Web_Stories\Embed_Base;
3434
use Google\Web_Stories\Model\Story;
35+
use Google\Web_Stories\Renderer\Stories\Renderer;
3536

3637
/**
3738
* Class Singleton
@@ -112,14 +113,31 @@ public function render( array $args = [] ): string {
112113
(int) $args['height']
113114
);
114115

116+
$this->assets->enqueue_style_asset( Renderer::STYLE_HANDLE ); // For the lightbox styles.
115117
$this->assets->enqueue_style( AMP_Story_Player_Assets::SCRIPT_HANDLE );
116118
$this->assets->enqueue_script( AMP_Story_Player_Assets::SCRIPT_HANDLE );
117119
$this->assets->enqueue_style_asset( Embed_Base::SCRIPT_HANDLE );
118120

119121
ob_start();
120122
?>
121-
<div class="<?php echo esc_attr( "$class web-stories-singleton $align" ); ?>" data-id="<?php echo esc_attr( 'singleton-' . $this->instance_id ); ?>">
122-
<div class="wp-block-embed__wrapper" style="<?php echo esc_attr( $wrapper_style ); ?>">
123+
<div
124+
class="<?php echo esc_attr( "$class web-stories-singleton $align" ); ?>"
125+
data-id="<?php echo esc_attr( 'singleton-' . $this->instance_id ); ?>"
126+
data-wp-interactive="web-stories-block"
127+
<?php
128+
// phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
129+
echo wp_interactivity_data_wp_context(
130+
[
131+
'instanceId' => $this->instance_id,
132+
]
133+
);
134+
?>
135+
>
136+
<div
137+
class="wp-block-embed__wrapper"
138+
style="<?php echo esc_attr( $wrapper_style ); ?>"
139+
data-wp-on--click="actions.open"
140+
>
123141
<?php $this->render_story_with_poster( $args ); ?>
124142
</div>
125143
<?php
@@ -141,12 +159,14 @@ public function render( array $args = [] ): string {
141159

142160
?>
143161
<div class="web-stories-singleton__lightbox-wrapper <?php echo esc_attr( 'ws-lightbox-singleton-' . $this->instance_id ); ?>">
144-
<div class="web-stories-singleton__lightbox">
162+
<div
163+
class="web-stories-singleton__lightbox"
164+
id="<?php echo esc_attr( 'ws-lightbox-singleton-' . $this->instance_id ); ?>"
165+
>
145166
<amp-story-player
146167
width="3.6"
147168
height="6"
148169
layout="responsive"
149-
data-wp-interactive="web-stories-block"
150170
data-wp-on--amp-story-player-close="actions.close"
151171
data-wp-on--navigation="actions.navigation"
152172
>

package-lock.json

+16-18
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

packages/stories-block-view/package.json

-33
This file was deleted.

packages/stories-block/package.json

+1
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@
4343
"@wordpress/element": "^6.19.0",
4444
"@wordpress/i18n": "^4.47.0",
4545
"@wordpress/icons": "^9.38.0",
46+
"@wordpress/interactivity": "^6.19.0",
4647
"@wordpress/notices": "^4.15.0",
4748
"@wordpress/url": "^3.48.0",
4849
"@wordpress/viewport": "^5.24.0",

packages/stories-block/src/css/singleton.css

+1
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@
5353
aspect-ratio: var(--aspect-ratio);
5454
border-radius: 8px;
5555
overflow: hidden;
56+
cursor: pointer;
5657
}
5758

5859
.web-stories-singleton-poster a {

packages/stories-block-view/src/index.js renamed to packages/stories-block/src/view.ts

+86-24
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2024 Google LLC
2+
* Copyright 2025 Google LLC
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -19,16 +19,66 @@
1919
*/
2020
import { store, getContext, getElement } from '@wordpress/interactivity';
2121

22+
interface StoryDef {
23+
href: string;
24+
title: string | null;
25+
posterImage: string | null;
26+
idx: number;
27+
distance: number;
28+
storyContentLoaded: boolean;
29+
desktopAspectRatio: number | null;
30+
}
31+
32+
interface AmpStoryPlayerElement extends HTMLElement {
33+
getStories: () => StoryDef[];
34+
play: () => void;
35+
pause: () => void;
36+
rewind: () => void;
37+
mute: () => void;
38+
show: (href: string) => void;
39+
}
40+
41+
interface AmpStoryPlayerNavigationEvent extends Event {
42+
detail: {
43+
index: number;
44+
remaining: number;
45+
};
46+
}
47+
48+
type State = {
49+
lightboxElement: HTMLElement | null;
50+
player: null | AmpStoryPlayerElement;
51+
stories: StoryDef[];
52+
instanceId: string | null;
53+
currentLocation: string | null;
54+
};
55+
56+
type BlockContext = {
57+
instanceId: string;
58+
};
59+
60+
function runWithViewTransition(f: () => void) {
61+
if (!document.startViewTransition) {
62+
f();
63+
} else {
64+
document.startViewTransition(() => f());
65+
}
66+
}
67+
2268
const { state, actions } = store('web-stories-block', {
2369
state: {
2470
lightboxElement: null,
2571
player: null,
26-
stories: null,
72+
stories: [],
2773
instanceId: null,
2874
currentLocation: null,
29-
},
75+
} as State,
3076
actions: {
31-
storyContentReady: (storyObject, callback, maxRetries = 5) => {
77+
storyContentReady: (
78+
storyObject: StoryDef,
79+
callback: () => void,
80+
maxRetries = 5
81+
) => {
3282
const stateIntervalObj = setInterval(() => {
3383
if (storyObject.storyContentLoaded === true) {
3484
window.clearInterval(stateIntervalObj);
@@ -52,44 +102,56 @@ const { state, actions } = store('web-stories-block', {
52102
player.pause();
53103
player.mute();
54104

55-
lightboxElement.classList.toggle('show');
105+
lightboxElement?.classList.toggle('show');
56106
document.body.classList.toggle('web-stories-lightbox-open');
57107
},
58-
open: (event) => {
108+
open: (event: Event) => {
59109
event.preventDefault();
60-
const { ref: card } = getElement();
61-
const context = JSON.parse(getContext().replaceAll("'", ''));
110+
const context = getContext<BlockContext>();
62111
const lightboxElement =
63112
document.querySelector(
64113
`.ws-lightbox-${context.instanceId} .web-stories-list__lightbox`
65114
) ||
66115
document.querySelector(
67-
`.ws-lightbox-${context.instanceId} .web-stories-singleton__lightbox`
116+
`.ws-lightbox-singleton-${context.instanceId} .web-stories-singleton__lightbox`
68117
);
69-
const player = lightboxElement.querySelector('amp-story-player');
118+
119+
if (!lightboxElement) {
120+
return;
121+
}
122+
123+
const player = lightboxElement.querySelector(
124+
'amp-story-player'
125+
) as unknown as AmpStoryPlayerElement;
70126
const stories = player.getStories();
71127

72-
state.lightboxElement = lightboxElement;
128+
state.lightboxElement = lightboxElement as HTMLElement;
73129
state.player = player;
74130
state.stories = stories;
75131
state.instanceId = context.instanceId;
76132
state.currentLocation = location.href;
77133

134+
const { ref: card } = getElement();
135+
78136
const storyObject = stories.find(
79-
(story) => story.href === card.querySelector('a').href
137+
(story) => story.href === card?.querySelector('a')?.href
80138
);
81139

82-
player.show(storyObject.href);
83-
player.play();
140+
if (storyObject) {
141+
player.show(storyObject.href);
142+
player.play();
84143

85-
actions.storyContentReady(storyObject, () => {
86-
history.pushState({}, '', storyObject.href);
87-
});
144+
actions.storyContentReady(storyObject, () => {
145+
history.pushState({}, '', storyObject.href);
146+
});
147+
}
88148

89-
lightboxElement.classList.toggle('show');
90-
document.body.classList.toggle('web-stories-lightbox-open');
149+
runWithViewTransition(() => {
150+
lightboxElement.classList.toggle('show');
151+
document.body.classList.toggle('web-stories-lightbox-open');
152+
});
91153
},
92-
navigation: (event) => {
154+
navigation: (event: AmpStoryPlayerNavigationEvent) => {
93155
const storyObject = state.stories[event.detail.index];
94156
if (storyObject && storyObject.href !== document.location.href) {
95157
actions.storyContentReady(storyObject, () => {
@@ -100,20 +162,20 @@ const { state, actions } = store('web-stories-block', {
100162
onPopstate: () => {
101163
const lightboxElement = state.lightboxElement;
102164
const player = state.player;
103-
const isLightboxOpen = lightboxElement.classList.contains('show');
165+
const isLightboxOpen = lightboxElement?.classList.contains('show');
104166

105167
const storyObject = state.stories.find(
106168
(story) => story.href === document.location.href
107169
);
108170

109171
if (storyObject) {
110172
if (!isLightboxOpen) {
111-
lightboxElement.classList.toggle('show');
173+
lightboxElement?.classList.toggle('show');
112174
document.body.classList.toggle('web-stories-lightbox-open');
113-
player.play();
175+
player?.play();
114176
}
115177

116-
player.show(storyObject.href);
178+
player?.show(storyObject.href);
117179
} else if (isLightboxOpen) {
118180
actions.close();
119181
}

packages/stories-block/tsconfig.json

+12
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
{
2+
"extends": "../../tsconfig.shared.json",
3+
"compilerOptions": {
4+
"rootDir": "src",
5+
"declarationDir": "dist-types"
6+
},
7+
"references": [],
8+
"files": ["../../node_modules/jest-extended/types/index.d.ts"],
9+
"include": [
10+
"src/view.ts"
11+
]
12+
}

tsconfig.json

+1
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
{ "path": "packages/react" },
1919
{ "path": "packages/rich-text" },
2020
{ "path": "packages/stickers" },
21+
{ "path": "packages/stories-block" },
2122
{ "path": "packages/story-editor" },
2223
{ "path": "packages/templates" },
2324
{ "path": "packages/test-utils" },

0 commit comments

Comments
 (0)