PluginProbe
ActivityPub / 7.8.2
ActivityPub v7.8.2
9.3.1 9.3.0 9.2.2 9.2.1 9.2.0 9.1.0 9.0.2 9.0.1 9.0.0 8.3.0 8.2.1 8.2.0 8.1.1 1.0.5 1.0.6 1.0.7 1.0.8 1.0.9 1.1.0 1.2.0 1.3.0 2.0.0 2.0.1 2.1.0 2.1.1 All 160 releases
← All changes | build/reactions/render.php +41 -203 8.2.0 → 7.8.2 View file →
@@ -7,11 +7,9 @@
7 7
8 8 use Activitypub\Blocks;
9 9 use Activitypub\Comment;
10 10
11 -use function Activitypub\get_post_id;
12 11 use function Activitypub\is_activitypub_request;
13 -use function Activitypub\is_post_publicly_queryable;
14 12
15 13 if ( is_activitypub_request() || is_feed() ) {
16 14 return;
17 15 }
@@ -24,9 +22,8 @@
24 22 $attributes,
25 23 array(
26 24 'align' => null,
27 25 'displayStyle' => $default_display_style,
28 - 'showActions' => false,
29 26 )
30 27 );
31 28
32 29 /* @var \WP_Block $block Current block. */
@@ -50,13 +47,8 @@
50 47
51 48 // Get the Post ID from attributes or use the current post.
52 49 $_post_id = $attributes['postId'] ?? get_the_ID();
53 50
54 -// Don't leak reaction metadata for posts that are not currently publicly queryable.
55 -if ( ! is_post_publicly_queryable( $_post_id ) ) {
56 - return;
57 -}
58 -
59 51 // Generate a unique ID for the block.
60 52 $block_id = 'activitypub-reactions-block-' . wp_unique_id();
61 53
62 54 /*
@@ -116,33 +108,22 @@
116 108 ),
117 109 );
118 110 }
119 111
120 -if ( empty( $reactions ) && ! $attributes['showActions'] ) {
112 +if ( empty( $reactions ) ) {
121 113 echo '<!-- Reactions block: No reactions found. -->';
122 114 return;
123 115 }
124 116
125 117 // Set up the Interactivity API config.
126 -$config = array(
127 - 'defaultAvatarUrl' => ACTIVITYPUB_PLUGIN_URL . 'assets/img/mp.jpg',
128 - 'namespace' => ACTIVITYPUB_REST_NAMESPACE,
118 +wp_interactivity_config(
119 + 'activitypub/reactions',
120 + array(
121 + 'defaultAvatarUrl' => ACTIVITYPUB_PLUGIN_URL . 'assets/img/mp.jpg',
122 + 'namespace' => ACTIVITYPUB_REST_NAMESPACE,
123 + )
129 124 );
130 125
131 -if ( $attributes['showActions'] ) {
132 - $config['i18n'] = array(
133 - 'copied' => __( 'Copied!', 'activitypub' ),
134 - 'copy' => __( 'Copy', 'activitypub' ),
135 - 'emptyProfileError' => __( 'Please enter a profile URL or handle.', 'activitypub' ),
136 - 'genericError' => __( 'An error occurred. Please try again.', 'activitypub' ),
137 - 'intentLabelLike' => __( 'Like this post', 'activitypub' ),
138 - 'intentLabelAnnounce' => __( 'Boost this post', 'activitypub' ),
139 - 'invalidProfileError' => __( 'Please enter a valid profile URL or handle.', 'activitypub' ),
140 - );
141 -}
142 -
143 -wp_interactivity_config( 'activitypub/reactions', $config );
144 -
145 126 // Set up the Interactivity API state.
146 127 wp_interactivity_state( 'activitypub/reactions', array( 'reactions' => array( $_post_id => $reactions ) ) );
147 128
148 129 // Render a subset of the most recent reactions for facepile.
@@ -168,55 +149,23 @@
168 149 'modal' => array(
169 150 'isCompact' => true,
170 151 'isOpen' => false,
171 152 'items' => array(),
172 - 'title' => '',
173 153 ),
174 154 'postId' => $_post_id,
175 155 'reactions' => $reactions,
176 156 );
177 157
178 -if ( $attributes['showActions'] ) {
179 - $context['modal']['intent'] = '';
180 - $context['copyButtonText'] = __( 'Copy', 'activitypub' );
181 - $context['errorMessage'] = '';
182 - $context['isError'] = false;
183 - $context['isLoading'] = false;
184 - $context['postUrl'] = get_post_id( $_post_id );
185 - $context['remoteProfile'] = '';
186 - $context['shouldSaveProfile'] = true;
187 -}
188 -
189 -// Map comment types to remote intent types.
190 -$intent_map = array(
191 - 'like' => 'like',
192 - 'repost' => 'announce',
193 - 'quote' => 'announce',
194 -);
195 -
196 158 // Build reactions content.
197 159 ob_start();
198 160 ?>
199 161 <div class="activitypub-reactions">
200 162 <?php
201 - // First pass: render reaction types that have items (full treatment).
202 163 foreach ( $reactions as $_type => $reaction ) :
203 164 /* translators: %s: reaction type. */
204 165 $aria_label = sprintf( __( 'View all %s', 'activitypub' ), Comment::get_comment_type_attr( $_type, 'label' ) );
205 - $intent = isset( $intent_map[ $_type ] ) ? $intent_map[ $_type ] : '';
206 166 ?>
207 167 <div class="reaction-group" data-reaction-type="<?php echo esc_attr( $_type ); ?>">
208 - <?php if ( $attributes['showActions'] && $intent ) : ?>
209 - <button
210 - class="reaction-action-button has-text-color has-background"
211 - data-intent="<?php echo esc_attr( $intent ); ?>"
212 - data-wp-on--click="actions.openIntentModal"
213 - type="button"
214 - aria-label="<?php echo esc_attr( Comment::get_comment_type_attr( $_type, 'singular' ) ); ?>"
215 - >
216 - <?php echo esc_html( Comment::get_comment_type_attr( $_type, 'singular' ) ); ?>
217 - </button>
218 - <?php endif; ?>
219 168 <?php if ( $show_avatars ) : ?>
220 169 <ul class="reaction-avatars">
221 170 <template data-wp-each="context.reactions.<?php echo esc_attr( $_type ); ?>.items">
222 171 <li>
@@ -241,12 +190,11 @@
241 190 </template>
242 191 </ul>
243 192 <?php endif; ?>
244 193 <button
245 - class="reaction-label has-text-color has-background"
194 + class="reaction-label wp-element-button"
246 195 data-reaction-type="<?php echo esc_attr( $_type ); ?>"
247 196 data-wp-on--click="actions.toggleModal"
248 - type="button"
249 197 aria-label="<?php echo esc_attr( $aria_label ); ?>"
250 198 >
251 199 <?php echo esc_html( $reaction['label'] ); ?>
252 200 </button>
@@ -251,165 +199,55 @@
251 199 <?php echo esc_html( $reaction['label'] ); ?>
252 200 </button>
253 201 </div>
254 202 <?php endforeach; ?>
255 - <?php
256 - // Second pass: render action buttons for reaction types without items.
257 - if ( $attributes['showActions'] ) :
258 - $empty_types = array_diff_key( $intent_map, $reactions );
259 -
260 - if ( ! empty( $empty_types ) ) :
261 - ?>
262 - <div class="reaction-actions-only" role="group" aria-label="<?php esc_attr_e( 'Reaction actions', 'activitypub' ); ?>">
263 - <?php foreach ( $empty_types as $_type => $intent ) : ?>
264 - <button
265 - class="reaction-action-button has-text-color has-background"
266 - data-intent="<?php echo esc_attr( $intent ); ?>"
267 - data-wp-on--click="actions.openIntentModal"
268 - type="button"
269 - aria-label="<?php echo esc_attr( Comment::get_comment_type_attr( $_type, 'singular' ) ); ?>"
270 - >
271 - <?php echo esc_html( Comment::get_comment_type_attr( $_type, 'singular' ) ); ?>
272 - </button>
273 - <?php endforeach; ?>
274 - </div>
275 - <?php
276 - endif;
277 - endif;
278 - ?>
279 203 </div>
280 204 <?php
281 205 $reactions_content = ob_get_clean();
282 206
283 -// Build modal content: reactors list (compact) + intent dialog (full-size).
207 +// Build modal content.
284 208 ob_start();
285 209 ?>
286 -<div data-wp-bind--hidden="!context.modal.isCompact">
287 - <ul class="reactions-list">
288 - <template data-wp-each="context.modal.items">
289 - <li class="reaction-item">
290 - <a data-wp-bind--href="context.item.url" target="_blank" rel="noopener noreferrer">
291 - <?php if ( $show_avatars ) : ?>
292 - <img
293 - alt=""
294 - data-wp-bind--alt="context.item.name"
295 - data-wp-bind--src="context.item.avatar"
296 - data-wp-on--error="callbacks.setDefaultAvatar"
297 - src=""
298 - />
299 - <?php endif; ?>
300 - <span class="reaction-name" data-wp-text="context.item.name"></span>
301 - </a>
302 - </li>
303 - </template>
304 - </ul>
305 -</div>
306 -<?php if ( $attributes['showActions'] ) : ?>
307 -<div class="activitypub-intent-dialog" data-wp-bind--hidden="context.modal.isCompact">
308 - <div class="activitypub-dialog__section">
309 - <h4><?php esc_html_e( 'Post URL', 'activitypub' ); ?></h4>
310 - <div class="activitypub-dialog__description">
311 - <?php esc_html_e( 'Paste the post URL into the search field of your favorite open social app or platform.', 'activitypub' ); ?>
312 - </div>
313 - <div class="activitypub-dialog__button-group">
314 - <label for="<?php echo esc_attr( $block_id . '-post-url' ); ?>" class="screen-reader-text">
315 - <?php esc_html_e( 'Post URL', 'activitypub' ); ?>
316 - </label>
317 - <input
318 - aria-readonly="true"
319 - class="wp-block-search__input"
320 - id="<?php echo esc_attr( $block_id . '-post-url' ); ?>"
321 - readonly
322 - tabindex="-1"
323 - type="text"
324 - data-wp-bind--value="context.postUrl"
325 - />
326 - <button
327 - aria-label="<?php esc_attr_e( 'Copy URL to clipboard', 'activitypub' ); ?>"
328 - class="wp-element-button"
329 - data-wp-on--click="actions.copyPostUrl"
330 - type="button"
331 - >
332 - <span data-wp-text="context.copyButtonText"></span>
333 - </button>
334 - </div>
335 - </div>
336 - <div class="activitypub-dialog__section">
337 - <h4><?php esc_html_e( 'Your Profile', 'activitypub' ); ?></h4>
338 - <div class="activitypub-dialog__description">
339 - <?php esc_html_e( 'Or, if you know your own profile, we can start things that way!', 'activitypub' ); ?>
340 - <?php Blocks::render_modal_help(); ?>
341 - </div>
342 - <div class="activitypub-dialog__button-group">
343 - <label for="<?php echo esc_attr( $block_id . '-remote-profile' ); ?>" class="screen-reader-text">
344 - <?php esc_html_e( 'Your Fediverse profile', 'activitypub' ); ?>
345 - </label>
346 - <input
347 - class="wp-block-search__input"
348 - data-wp-bind--aria-invalid="context.isError"
349 - data-wp-bind--value="context.remoteProfile"
350 - data-wp-on--input="actions.updateIntentProfile"
351 - data-wp-on--keydown="actions.onIntentKeydown"
352 - id="<?php echo esc_attr( $block_id . '-remote-profile' ); ?>"
353 - placeholder="<?php esc_attr_e( '@[email protected]', 'activitypub' ); ?>"
354 - type="text"
355 - />
356 - <button
357 - class="wp-element-button"
358 - data-wp-bind--disabled="context.isLoading"
359 - data-wp-on--click="actions.submitIntent"
360 - type="button"
361 - >
362 - <span data-wp-bind--hidden="context.isLoading"><?php esc_html_e( 'Go', 'activitypub' ); ?></span>
363 - <span data-wp-bind--hidden="!context.isLoading"><?php esc_html_e( 'Loading…', 'activitypub' ); ?></span>
364 - </button>
365 - </div>
366 - <div
367 - class="activitypub-dialog__error"
368 - data-wp-bind--hidden="!context.isError"
369 - data-wp-text="context.errorMessage"
370 - ></div>
371 - <div class="activitypub-dialog__remember">
372 - <label>
373 - <input
374 - checked
375 - data-wp-bind--checked="context.shouldSaveProfile"
376 - data-wp-on--change="actions.toggleRememberProfile"
377 - type="checkbox"
210 +<ul class="reactions-list">
211 + <template data-wp-each="context.modal.items">
212 + <li class="reaction-item">
213 + <a data-wp-bind--href="context.item.url" target="_blank" rel="noopener noreferrer">
214 + <?php if ( $show_avatars ) : ?>
215 + <img
216 + alt=""
217 + data-wp-bind--alt="context.item.name"
218 + data-wp-bind--src="context.item.avatar"
219 + data-wp-on--error="callbacks.setDefaultAvatar"
220 + src=""
378 221 />
379 - <?php esc_html_e( 'Remember my profile for future interactions.', 'activitypub' ); ?>
380 - </label>
381 - </div>
382 - </div>
383 -</div>
384 -<?php endif; ?>
222 + <?php endif; ?>
223 + <span class="reaction-name" data-wp-text="context.item.name"></span>
224 + </a>
225 + </li>
226 + </template>
227 +</ul>
385 228 <?php
386 229 $modal_content = ob_get_clean();
387 230
388 -// Render the shared modal with both contents.
389 -$modal_args = array(
390 - 'content' => $modal_content,
231 +// Combine reactions and modal.
232 +ob_start();
233 +Blocks::render_modal(
234 + array(
235 + 'is_compact' => true,
236 + 'content' => $modal_content,
237 + )
391 238 );
392 -
393 -if ( $attributes['showActions'] ) {
394 - $modal_args['title_binding'] = 'context.modal.title';
395 -} else {
396 - $modal_args['is_compact'] = true;
397 -}
398 -
399 -ob_start();
400 -Blocks::render_modal( $modal_args );
401 239 $inner_content = $reactions_content . ob_get_clean();
402 240
403 -$wrapper_attrs = array(
404 - 'id' => $block_id,
405 - 'class' => $attributes['className'] ?? '',
406 - 'data-wp-interactive' => 'activitypub/reactions',
407 - 'data-wp-context' => wp_json_encode( $context, JSON_HEX_TAG | JSON_HEX_APOS | JSON_HEX_QUOT | JSON_HEX_AMP ),
408 - 'data-wp-init' => 'callbacks.initReactions',
241 +$wrapper_attributes = get_block_wrapper_attributes(
242 + array(
243 + 'id' => $block_id,
244 + 'class' => $attributes['className'] ?? '',
245 + 'data-wp-interactive' => 'activitypub/reactions',
246 + 'data-wp-context' => wp_json_encode( $context, JSON_HEX_TAG | JSON_HEX_APOS | JSON_HEX_QUOT | JSON_HEX_AMP ),
247 + 'data-wp-init' => 'callbacks.initReactions',
248 + )
409 249 );
410 -
411 -$wrapper_attributes = get_block_wrapper_attributes( $wrapper_attrs );
412 250
413 251 // Render the block with common wrapper.
414 252 ?>
415 253 <div <?php echo $wrapper_attributes; // phpcs:ignore WordPress.Security.EscapeOutput ?>>