PluginProbe
Templately – Elementor & Gutenberg Template Library: 6500+ Free & Pro Ready Templates And Cloud! / 3.7.3
Templately – Elementor & Gutenberg Template Library: 6500+ Free & Pro Ready Templates And Cloud! v3.7.3
3.7.5 3.7.4 3.7.3 3.7.2 1-final 3.7.1 3.7.0 3.6.8 3.6.7 3.6.6 3.6.5 3.6.4 3.6.3 3.6.2 3.6.1 3.0.3 3.0.4 3.0.5 3.0.6 3.0.7 3.0.8 3.0.9 3.1.0 3.1.1 3.1.10 All 111 releases
← All changes | includes/Core/Admin.php +69 -6 3.6.23.7.3 View file →
@@ -103,9 +103,9 @@
103 103 */
104 104 public function scripts( $hook = '' ) {
105 105 $allowed_hooks = apply_filters(
106 106 'templately_admin_enqueue_allowed_hooks',
107 - [ 'index.php', 'edit.php', 'toplevel_page_templately', 'elementor', 'gutenberg', 'templately_page_templately_settings' ],
107 + [ 'index.php', 'edit.php', 'plugins.php', 'toplevel_page_templately', 'elementor', 'gutenberg', 'templately_page_templately_settings' ],
108 108 $hook
109 109 );
110 110
111 111 if ( !empty($hook) && ! in_array( $hook, $allowed_hooks, true ) ) {
@@ -165,8 +165,24 @@
165 165 }
166 166 return;
167 167 }
168 168
169 + if ( 'plugins.php' === $hook ) {
170 + templately()->assets->enqueue(
171 + 'templately-inter',
172 + set_url_scheme( '//fonts.googleapis.com/css2?family=Inter:ital,opsz,wght@0,14..32,100..900;1,14..32,100..900&display=swap' )
173 + );
174 + templately()->assets->enqueue( 'templately-tailwind', 'css/tailwind.css', [ 'templately-inter' ] );
175 + templately()->assets->enqueue( 'templately-deactivate-survey', 'css/deactivate-survey-style.css', [ 'templately-tailwind' ] );
176 + templately()->assets->enqueue( 'templately', 'js/deactivate-survey.js', [ 'regenerator-runtime' ], true );
177 + templately()->assets->localize( 'templately', 'templatelyDeactivateSurvey', [
178 + 'nonce' => wp_create_nonce( 'templately_nonce' ),
179 + 'pluginBasename' => TEMPLATELY_PLUGIN_BASENAME,
180 + 'reasons' => DeactivationSurvey::get_reasons_for_js(),
181 + ] );
182 + return;
183 + }
184 +
169 185 $templately = [];
170 186
171 187 if ( 'edit.php' === $hook ) {
172 188 global $current_screen;
@@ -235,9 +251,9 @@
235 251
236 252 wp_enqueue_media();
237 253 templately()->assets->enqueue( 'templately', 'js/templately.js', $script_dependencies, true );
238 254 templately()->assets->enqueue( 'templately', 'css/templately.css', ['templately-dmsans', 'templately-inter'] );
239 - $tailwind_hooks = apply_filters( 'templately_tailwind_hooks', [ 'toplevel_page_templately', 'elementor', 'gutenberg', 'templately_page_templately_settings' ] );
255 + $tailwind_hooks = apply_filters( 'templately_tailwind_hooks', [ 'toplevel_page_templately', 'elementor', 'gutenberg', 'templately_page_templately_settings', 'edit.php' ] );
240 256 if ( in_array( $hook, $tailwind_hooks, true ) ) {
241 257 templately()->assets->enqueue( 'templately-tailwind', 'css/tailwind.css', ['templately', 'templately-inter'] );
242 258 }
243 259
@@ -271,13 +287,18 @@
271 287 'no_items' => templately()->assets->icon( 'no-items.png' ),
272 288 'loadingImage' => templately()->assets->icon( 'logos/loading-logo.gif' ),
273 289 'current_url' => admin_url( 'admin.php?page=templately' ),
274 290 'wp_dashboard_url' => admin_url( 'index.php' ),
291 + 'templately_library_url' => admin_url( 'edit.php?post_type=templately_library' ),
275 292 'is_signed' => Login::is_signed(),
276 293 'is_globally_signed' => Login::is_globally_signed(),
277 294 'signed_as_global' => Login::signed_as_global(),
278 295 'current_screen' => $_current_screen,
279 296 'can_fsi' => current_user_can('install_plugins') && current_user_can('install_themes'),
297 + // Account-level administration: the Subscription screen. Mirrors the
298 + // subscription branch of `Checkout::checkout()`, so the sidebar can hide
299 + // it for non-admins rather than route them to a 403.
300 + 'can_manage_account' => current_user_can( 'manage_options' ),
280 301 'post_type' => get_post_type(),
281 302 'has_elementor' => rest_sanitize_boolean( is_plugin_active( 'elementor/elementor.php' ) ),
282 303 'has_elementor_pro' => rest_sanitize_boolean( is_plugin_active( 'elementor-pro/elementor-pro.php' ) ),
283 304 'theme' => $_current_screen == 'templately' ? 'light' : $platform->ui_theme(),
@@ -288,8 +309,15 @@
288 309 'allowed_mime_types' => get_allowed_mime_types(),
289 310 'is_free_user' => $global_user === false || isset( $global_user['plan'] ) && $global_user['plan'] == 'free',
290 311 'is_disconnected' => ! empty( $global_user['is_disconnected'] ),
291 312 'tour_status' => Options::get_instance()->get( 'tour_status', [] ),
313 + // Which Templately site the plugin talks to. `templatelyDeveloper.dev_api`
314 + // carries the same flag, but only when developer mode is on and only from
315 + // its own script handle — so anything rendered before that handle runs (the
316 + // footer CTA, for one) linked to the live site while the plugin was pointed
317 + // at dev. Kept here, on the main localized object, `webURL()` is right from
318 + // the first paint. See `react-src/utils/helper.js#webURL`.
319 + 'dev_api' => Helper::is_dev_api(),
292 320 ], $templately );
293 321
294 322 // Apply filter to allow network admin modifications
295 323 $templately = apply_filters( 'templately_admin_localized_data', $templately );
@@ -367,9 +395,9 @@
367 395 'class' => 'dismiss-btn'
368 396 ]
369 397 ],
370 398 'support' => [
371 - 'link' => 'https://templately.com/?support=open',
399 + 'link' => Helper::web_url( '', [ 'support' => 'open' ] ),
372 400 'attributes' => [
373 401 'target' => '_blank'
374 402 ],
375 403 'label' => __( 'I need help', 'templately' ),
@@ -431,9 +459,9 @@
431 459 'thumbnail' => templately()->assets->icon( 'logos/logo-full.svg' ),
432 460 'html' => $_notice_text_spring_savings_2026,
433 461 'links' => [
434 462 'later' => [
435 - 'link' => 'https://templately.com/#pricing',
463 + 'link' => Helper::web_url() . '#pricing',
436 464 'target' => '_blank',
437 465 'label' => __( 'Upgrade To Pro Now', 'templately' ),
438 466 'attributes' => [
439 467 'class' => 'button button-primary',
@@ -471,9 +499,9 @@
471 499 $holiday_text .= "<div class='wpnotice-button-wrapper'>";
472 500 $holiday_text .= sprintf(
473 501 '<a class="button button-primary" target="_blank" href="%2$s">%1$s</a>',
474 502 $crown . __('GET PRO Lifetime Access', 'templately'),
475 - 'https://templately.com/#pricing'
503 + Helper::web_url() . '#pricing'
476 504 );
477 505 $holiday_text .= sprintf(
478 506 '<button class="button button-link dismiss-btn" data-dismiss="true">%1$s</button>',
479 507 __('No, I\'ll Pay Full Price Later', 'templately'),
@@ -526,9 +554,44 @@
526 554 // ], '58.7' );
527 555 }
528 556
529 557 public function display() {
530 - Helper::views( 'template-library' );
558 + Helper::views( 'template-library', [
559 + 'show_grid_skeleton' => $this->is_template_library_path(),
560 + ] );
561 + }
562 +
563 + /**
564 + * Whether the current `?path=` targets the template-library grid
565 + * (`TemplatesTypeLayout`, e.g. `elementor/packs`) — the only route the
566 + * pre-mount skeleton's card grid actually matches. Every other route
567 + * (`clouds/*`, `downloads`, `favourites`, `subscription`,
568 + * `purchased-items`, `ai-sites`, `settings/*`, item-detail pages, and
569 + * Saved Templates) gets a generic shell instead, so a hard reload doesn't
570 + * flash the wrong page shape before React mounts. See
571 + * views/template-library.php.
572 + *
573 + * @return bool
574 + */
575 + private function is_template_library_path() {
576 + $path = isset( $_GET['path'] ) ? sanitize_text_field( wp_unslash( $_GET['path'] ) ) : '';
577 +
578 + if ( $path === '' ) {
579 + return true;
580 + }
581 +
582 + $segments = array_values( array_filter( explode( '/', trim( $path, '/' ) ) ) );
583 +
584 + $non_library_prefixes = [ 'clouds', 'downloads', 'favourites', 'subscription', 'purchased-items', 'ai-sites', 'settings' ];
585 +
586 + if ( in_array( $segments[0] ?? '', $non_library_prefixes, true ) ) {
587 + return false;
588 + }
589 +
590 + // `/:platform/:type` (the grid) vs `/:platform/:type/:slug` (item
591 + // detail, its own skeleton shape) or `/:platform/templates` (Saved
592 + // Templates, a table) — only the 2-segment form matches the grid.
593 + return count( $segments ) === 2 && $segments[1] !== 'templates';
531 594 }
532 595
533 596 /**
534 597 * If Elementor doesn't exists.