← All changes
|
src/DonationForms/ViewModels/DonationFormViewModel.php
+49
-1
4.16.7
→
4.17.0
View file →
| @@ -6,10 +6,13 @@ | ||
| 6 | 6 | use Give\Campaigns\ValueObjects\CampaignGoalType; |
| 7 | 7 | use Give\DonationForms\Actions\GenerateAuthUrl; |
| 8 | 8 | use Give\DonationForms\Actions\GenerateDonateRouteUrl; |
| 9 | 9 | use Give\DonationForms\Actions\GenerateDonationFormValidationRouteUrl; |
| 10 | +use Give\DonationForms\Actions\GetFormSkeletonData; | |
| 10 | 11 | use Give\DonationForms\Actions\IsolateEnqueuedFormViewAssets; |
| 12 | +use Give\DonationForms\Actions\RenderFormSkeleton; | |
| 11 | 13 | use Give\DonationForms\DataTransferObjects\DonationFormGoalData; |
| 14 | +use Give\DonationForms\Models\DonationForm; | |
| 12 | 15 | use Give\DonationForms\Properties\FormSettings; |
| 13 | 16 | use Give\DonationForms\Repositories\DonationFormRepository; |
| 14 | 17 | use Give\DonationForms\ValueObjects\GoalType; |
| 15 | 18 | use Give\Framework\Blocks\BlockCollection; |
| @@ -47,9 +50,18 @@ | ||
| 47 | 50 | /** |
| 48 | 51 | * @var bool |
| 49 | 52 | */ |
| 50 | 53 | private $previewMode; |
| 54 | + | |
| 51 | 55 | /** |
| 56 | + * The skeleton markup for this render, or empty when there is none to show. | |
| 57 | + * | |
| 58 | + * @since 4.17.0 | |
| 59 | + * | |
| 60 | + * @var string | |
| 61 | + */ | |
| 62 | + private $skeleton = ''; | |
| 63 | + /** | |
| 52 | 64 | * @since 4.1.0 |
| 53 | 65 | */ |
| 54 | 66 | private DonationFormGoalData $donationFormGoalData; |
| 55 | 67 | |
| @@ -145,8 +157,15 @@ | ||
| 145 | 157 | wp_strip_all_tags(give_get_option('custom_form_styles', '')) |
| 146 | 158 | ); |
| 147 | 159 | |
| 148 | 160 | wp_enqueue_style('givewp-base-form-styles'); |
| 161 | + | |
| 162 | + // The skeleton prints in the body before the app bundles load, so its styles go in the head with the rest. | |
| 163 | + if ($this->skeleton) { | |
| 164 | + wp_register_style('givewp-form-skeleton-styles', false); | |
| 165 | + wp_add_inline_style('givewp-form-skeleton-styles', (new RenderFormSkeleton())->css()); | |
| 166 | + wp_enqueue_style('givewp-form-skeleton-styles'); | |
| 167 | + } | |
| 149 | 168 | } |
| 150 | 169 | |
| 151 | 170 | /** |
| 152 | 171 | * @since 3.0.0 |
| @@ -275,8 +294,9 @@ | ||
| 275 | 294 | ]; |
| 276 | 295 | } |
| 277 | 296 | |
| 278 | 297 | /** |
| 298 | + * @since 4.17.0 print the form's skeleton inside the root and announce the shell to the embedding page. | |
| 279 | 299 | * This is the order of loading: |
| 280 | 300 | * 1. Enqueue global styles from WP. |
| 281 | 301 | * - This ensures template compatability with global WP css variables as needed. Loads before our templates, so they can use things like global font-family, etc. |
| 282 | 302 | * 2. Enqueue our donation form specific scripts & styles. |
| @@ -297,8 +317,10 @@ | ||
| 297 | 317 | * @since 3.0.0 |
| 298 | 318 | */ |
| 299 | 319 | public function render(): string |
| 300 | 320 | { |
| 321 | + $this->skeleton = $this->previewMode ? '' : $this->renderSkeleton(); | |
| 322 | + | |
| 301 | 323 | $this->enqueueGlobalStyles(); |
| 302 | 324 | |
| 303 | 325 | $this->enqueueFormScripts( |
| 304 | 326 | $this->donationFormId, |
| @@ -328,10 +350,14 @@ | ||
| 328 | 350 | ?> |
| 329 | 351 | |
| 330 | 352 | <div data-theme="light" id="root-givewp-donation-form" |
| 331 | 353 | data-iframe-height |
| 332 | - class="<?= esc_attr(implode(' ', $classNames)) ?>"></div> | |
| 354 | + class="<?= esc_attr(implode(' ', $classNames)) ?>"><?= $this->skeleton ?></div> | |
| 333 | 355 | |
| 356 | + <?php if ($this->skeleton): ?> | |
| 357 | + <script>parent.postMessage({type: 'givewp-embed-shell', height: document.documentElement.scrollHeight}, '*');</script> | |
| 358 | + <?php endif; ?> | |
| 359 | + | |
| 334 | 360 | <?php |
| 335 | 361 | wp_print_footer_scripts(); |
| 336 | 362 | |
| 337 | 363 | echo ob_get_clean(); |
| @@ -336,8 +362,30 @@ | ||
| 336 | 362 | |
| 337 | 363 | echo ob_get_clean(); |
| 338 | 364 | |
| 339 | 365 | exit(); |
| 366 | + } | |
| 367 | + | |
| 368 | + /** | |
| 369 | + * The skeleton RenderFormSkeleton draws, printed inside the root so the iframe shows the form's | |
| 370 | + * shape as soon as its HTML and head styles arrive, before the app bundles load. createRoot() | |
| 371 | + * replaces it with the form. The inline script that follows the root tells the embedding page | |
| 372 | + * the shell has painted and how tall it is; the payload is that height and nothing else, so it | |
| 373 | + * is addressed to any origin and the embed authenticates the message by its origin and source | |
| 374 | + * instead. Both are skipped for an unknown design, where there is nothing to show, and in the | |
| 375 | + * builder preview. | |
| 376 | + * | |
| 377 | + * @since 4.17.0 | |
| 378 | + */ | |
| 379 | + private function renderSkeleton(): string | |
| 380 | + { | |
| 381 | + $form = DonationForm::find($this->donationFormId); | |
| 382 | + | |
| 383 | + if (!$form) { | |
| 384 | + return ''; | |
| 385 | + } | |
| 386 | + | |
| 387 | + return (new RenderFormSkeleton())((new GetFormSkeletonData())($form)); | |
| 340 | 388 | } |
| 341 | 389 | |
| 342 | 390 | /** |
| 343 | 391 | * Loads scripts in order: [Registrars, Designs, Gateways, Block] |