Make WordPress Themes

Changeset 357072


Ignore:
Timestamp:
11/04/2026 05:35:33 AM (8 hours ago)
Author:
themedropbox
Message:

New version of PortfolioX Dark - 1.0.14

Location:
portfoliox-dark/1.0.14
Files:
10 edited
1 copied

Legend:

Unmodified
Added
Removed
  • portfoliox-dark/1.0.14/actions/header-actions.php

    r166704 r357072  
    1717                        'menu_id'        => 'portfoliox-menu',
    1818                        'menu_class'        => 'portfoliox-menu',
     19                        'fallback_cb'       => 'portfoliox_dark_menu_fallback',
    1920                ));
    2021                ?>
    … …  
    125126                                        'menu_id'        => 'wsm-menu',
    126127                                        'menu_class'        => 'wsm-menu',
    127                                 ));
     128                                        'fallback_cb'       => 'portfoliox_dark_menu_fallback',
     129                ));
    128130                                ?>
    129131                        </nav><!-- #site-navigation -->
  • portfoliox-dark/1.0.14/assets/css/main.css

    r254744 r357072  
    969969  }
    970970}
     971
     972/* ==========================================================================
     973   Header Logo & Navigation Spacing Rule (Collision Prevention)
     974   Ensures at least 30-40px gap between logo and menu so they never touch.
     975   ========================================================================== */
     976@media (min-width: 992px) {
     977  .menubar-content,
     978  .pxm-style1 .navigation .d-flex,
     979  .navigation .d-flex,
     980  .site-header .d-flex,
     981  .header-main-wrapper .d-flex {
     982    gap: 35px;
     983  }
     984
     985  .head-logo-sec,
     986  .pxms1-logo,
     987  .site-branding.brand-logo,
     988  .site-branding.brand-text,
     989  .menubar-content .head-logo-sec,
     990  .header-logo-wrap {
     991    flex-shrink: 0;
     992    margin-right: 30px;
     993  }
     994
     995  .main-navigation,
     996  .pxms1-menu,
     997  .real-estate-pack-container.menu-inner {
     998    min-width: 0;
     999  }
     1000}
  • portfoliox-dark/1.0.14/functions.php

    r341891 r357072  
    340340
    341341// Recommended plugins
    342 require get_template_directory() . '/inc/recommended-plugins.php';
     342require_once get_template_directory() . '/inc/recommended-plugins.php';
     343
     344
     345/**
     346 * Fallback menu for PortfolioX Dark
     347 * Limits fallback menu display to a maximum of 7 items (Home + up to 6 published pages)
     348 * to prevent header layout break when no custom menu is assigned.
     349 *
     350 * @param array|object $args Arguments passed from wp_nav_menu.
     351 */
     352function portfoliox_dark_menu_fallback($args = array())
     353{
     354        $menu_id = is_array($args) && isset($args['menu_id']) ? $args['menu_id'] : (is_object($args) && isset($args->menu_id) ? $args->menu_id : 'portfoliox-dark-menu');
     355        $menu_class = is_array($args) && isset($args['menu_class']) ? $args['menu_class'] : (is_object($args) && isset($args->menu_class) ? $args->menu_class : 'portfoliox-dark-menu');
     356
     357        $menu = '<ul id="' . esc_attr($menu_id) . '" class="' . esc_attr($menu_class) . '">';
     358
     359        // 1. Add Home link as first item
     360        $home_current = (is_front_page() || is_home()) ? ' current-menu-item' : '';
     361        $menu .= '<li class="menu-item menu-item-home' . $home_current . '"><a href="' . esc_url(home_url('/')) . '">' . esc_html__('Home', 'portfoliox-dark') . '</a></li>';
     362
     363        // 2. Query up to 6 published pages, excluding static front page if configured
     364        $exclude_ids = array();
     365        $front_page_id = (int) get_option('page_on_front');
     366        if ($front_page_id > 0) {
     367                $exclude_ids[] = $front_page_id;
     368        }
     369
     370        $pages = get_pages(array(
     371                'number'      => 6,
     372                'sort_column' => 'menu_order, post_title',
     373                'sort_order'  => 'ASC',
     374                'post_status' => 'publish',
     375                'exclude'     => $exclude_ids,
     376        ));
     377
     378        if (!empty($pages)) {
     379                foreach ($pages as $page) {
     380                        $page_current = (is_page($page->ID)) ? ' current-menu-item' : '';
     381                        $menu .= '<li class="menu-item menu-item-type-post_type menu-item-object-page' . $page_current . '"><a href="' . esc_url(get_permalink($page->ID)) . '">' . esc_html($page->post_title) . '</a></li>';
     382                }
     383        }
     384
     385        $menu .= '</ul>';
     386
     387        echo $menu;
     388}
  • portfoliox-dark/1.0.14/inc/about/about.php

    r341891 r357072  
    302302add_action('after_setup_theme', 'portfoliox_dark_about_setup');
    303303
     304/**
     305 * Pro notice text (Modern SaaS Card Design)
     306 */
    304307function portfoliox_dark_pnotice_output()
    305308{
    306309        $current_theme = wp_get_theme();
    307310        $current_theme_name = $current_theme->get('Name');
     311        $pro_link  = esc_url('https://wpthemespace.com/product/portfoliox-pro/?add-to-cart=5925');
    308312        $demo_link = esc_url('https://wpthemespace.com/product/portfoliox-pro/');
    309         $pro_link = esc_url('https://wpthemespace.com/product/portfoliox-pro/?add-to-cart=5925');
    310313?>
    311314        <style>
    312                 .pxd-notice-wrap{background:#fff;border:1px solid #c3e1f7;border-radius:6px;padding:16px 20px;box-shadow:0 1px 3px rgba(0,0,0,.08),0 1px 2px rgba(0,0,0,.06);display:flex;flex-direction:column;gap:10px;width:100%;box-sizing:border-box}
    313                 .mgadin-notice .pxd-notice-wrap{margin:0 -26px;width:calc(100% + 52px);border-radius:0;border-left:none;border-right:none;padding:16px 26px}
    314                 .pxd-notice-title{font-size:17px;font-weight:700;color:#1d2327;line-height:1.3;margin:0;display:flex;align-items:center;gap:6px}
    315                 .pxd-notice-title span.pxd-star{font-size:18px}
    316                 .pxd-notice-desc{font-size:13px;line-height:1.55;color:#50575e;margin:0}
    317                 .pxd-notice-desc strong{color:#2271b1}
    318                 .pxd-notice-badges{display:flex;flex-wrap:wrap;gap:6px;margin-top:2px}
    319                 .pxd-badge{display:inline-flex;align-items:center;gap:4px;background:#f0f6fc;color:#2271b1;border:1px solid #c3e1f7;border-radius:3px;padding:3px 8px;font-size:12px;font-weight:500;line-height:1.4;white-space:nowrap}
    320                 .pxd-badge--highlight{background:#dff0d8;border-color:#b4d8a0;color:#1e7a1e}
    321                 .pxd-notice-cta{display:flex;align-items:center;gap:8px;flex-wrap:wrap;margin-top:2px}
    322                 .pxd-btn{display:inline-flex;align-items:center;gap:5px;border-radius:4px;font-size:13px;font-weight:600;text-decoration:none;cursor:pointer;border:none;line-height:1.4;transition:background .15s,border-color .15s,box-shadow .15s}
    323                 .pxd-btn--primary{background:#2271b1!important;border:1px solid #135e96;color:#fff!important;padding:5px 14px}
    324                 .pxd-btn--primary:hover{background:#135e96!important;border-color:#0e4a7a;color:#fff!important}
    325                 .pxd-btn--primary:focus{box-shadow:0 0 0 1px #fff,0 0 0 3px #2271b1;outline:none}
    326                 .pxd-btn--primary:visited{color:#fff!important}
    327                 .pxd-btn--secondary{background:#fff;border:1px solid #8c8f94;color:#2271b1;padding:5px 14px}
    328                 .pxd-btn--secondary:hover{background:#f6f7f7;border-color:#8c8f94;color:#135e96}
    329                 .pxd-btn--link{background:none;border:none;color:#8c8f94;padding:5px 8px;text-decoration:underline}
    330                 .pxd-btn--link:hover{color:#d63638}
    331                 .pxd-lifetime{background:linear-gradient(135deg,#dff0d8 0%,#f0f6fc 100%);border:1px solid #b4d8a0;border-radius:4px;padding:6px 12px;display:flex;align-items:center;gap:6px;margin-top:2px}
    332                 .pxd-lifetime-text{font-size:13px;font-weight:700;color:#1e7a1e;line-height:1.3}
    333                 .pxd-lifetime-sub{font-size:12px;color:#50575e;font-weight:400}
     315                @keyframes RedGlow {
     316                        0% { box-shadow: 0 4px 20px rgba(239, 68, 68, 0.15); border-color: rgba(239, 68, 68, 0.3); }
     317                        50% { box-shadow: 0 6px 28px rgba(239, 68, 68, 0.35); border-color: rgba(239, 68, 68, 0.65); }
     318                        100% { box-shadow: 0 4px 20px rgba(239, 68, 68, 0.15); border-color: rgba(239, 68, 68, 0.3); }
     319                }
     320                @keyframes BtnPulse {
     321                        0% { transform: scale(1); box-shadow: 0 4px 12px rgba(220, 38, 38, 0.35); }
     322                        50% { transform: scale(1.02); box-shadow: 0 6px 18px rgba(220, 38, 38, 0.55); }
     323                        100% { transform: scale(1); box-shadow: 0 4px 12px rgba(220, 38, 38, 0.35); }
     324                }
     325                @keyframes TagPulse {
     326                        0% { transform: scale(1); }
     327                        50% { transform: scale(1.04); }
     328                        100% { transform: scale(1); }
     329                }
     330                .portfoliox-dark-pro-notice-card {
     331                        background: #ffffff !important;
     332                        border: 1px solid rgba(239, 68, 68, 0.35) !important;
     333                        border-left: 5px solid #ef4444 !important;
     334                        border-radius: 12px !important;
     335                        padding: 24px 28px !important;
     336                        margin: 20px 0 !important;
     337                        box-shadow: 0 4px 20px rgba(239, 68, 68, 0.12) !important;
     338                        animation: RedGlow 3.5s ease-in-out infinite !important;
     339                        font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen-Sans, Ubuntu, Cantarell, "Helvetica Neue", sans-serif !important;
     340                        box-sizing: border-box !important;
     341                        position: relative !important;
     342                }
     343                .portfoliox-dark-pro-wrapper {
     344                        display: flex !important;
     345                        align-items: center !important;
     346                        justify-content: space-between !important;
     347                        gap: 32px !important;
     348                        flex-wrap: wrap !important;
     349                }
     350                .portfoliox-dark-pro-left {
     351                        flex: 1 1 560px !important;
     352                }
     353                .portfoliox-dark-pro-header {
     354                        display: flex !important;
     355                        align-items: center !important;
     356                        gap: 10px !important;
     357                        margin-bottom: 10px !important;
     358                        flex-wrap: wrap !important;
     359                }
     360                .portfoliox-dark-tag-pro {
     361                        background: linear-gradient(135deg, #ef4444 0%, #b91c1c 100%) !important;
     362                        color: #ffffff !important;
     363                        font-size: 11px !important;
     364                        font-weight: 800 !important;
     365                        letter-spacing: 1px !important;
     366                        padding: 3px 10px !important;
     367                        border-radius: 6px !important;
     368                        text-transform: uppercase !important;
     369                }
     370                .portfoliox-dark-tag-deal {
     371                        background: #fef2f2 !important;
     372                        color: #b91c1c !important;
     373                        border: 1px solid #fecaca !important;
     374                        font-size: 12px !important;
     375                        font-weight: 700 !important;
     376                        padding: 3px 10px !important;
     377                        border-radius: 6px !important;
     378                        animation: TagPulse 2.5s ease-in-out infinite !important;
     379                        display: inline-flex !important;
     380                        align-items: center !important;
     381                        gap: 5px !important;
     382                }
     383                .portfoliox-dark-pro-headline {
     384                        font-size: 20px !important;
     385                        font-weight: 800 !important;
     386                        color: #111827 !important;
     387                        margin: 0 0 10px 0 !important;
     388                        line-height: 1.35 !important;
     389                }
     390                .portfoliox-dark-pro-desc {
     391                        font-size: 13.5px !important;
     392                        line-height: 1.6 !important;
     393                        color: #4b5563 !important;
     394                        margin: 0 0 16px 0 !important;
     395                }
     396                .portfoliox-dark-pro-badges {
     397                        display: flex !important;
     398                        flex-wrap: wrap !important;
     399                        gap: 8px !important;
     400                }
     401                .portfoliox-dark-badge-item {
     402                        background: #f3f4f6 !important;
     403                        color: #374151 !important;
     404                        border: 1px solid #e5e7eb !important;
     405                        font-size: 11.5px !important;
     406                        font-weight: 600 !important;
     407                        padding: 4px 10px !important;
     408                        border-radius: 6px !important;
     409                        display: inline-flex !important;
     410                        align-items: center !important;
     411                        gap: 5px !important;
     412                }
     413                .portfoliox-dark-badge-item span {
     414                        color: #10b981 !important;
     415                        font-weight: bold !important;
     416                }
     417                .portfoliox-dark-pro-right {
     418                        display: flex !important;
     419                        flex-direction: column !important;
     420                        align-items: flex-end !important;
     421                        gap: 10px !important;
     422                }
     423                .portfoliox-dark-btn-cta {
     424                        background: linear-gradient(135deg, #ef4444 0%, #dc2626 100%) !important;
     425                        color: #ffffff !important;
     426                        font-size: 14px !important;
     427                        font-weight: 700 !important;
     428                        padding: 12px 24px !important;
     429                        border-radius: 8px !important;
     430                        text-decoration: none !important;
     431                        display: inline-flex !important;
     432                        align-items: center !important;
     433                        gap: 8px !important;
     434                        box-shadow: 0 4px 12px rgba(220, 38, 38, 0.35) !important;
     435                        animation: BtnPulse 2.8s ease-in-out infinite !important;
     436                        transition: all 0.2s ease !important;
     437                        border: none !important;
     438                }
     439                .portfoliox-dark-btn-cta:hover {
     440                        background: linear-gradient(135deg, #dc2626 0%, #b91c1c 100%) !important;
     441                        color: #ffffff !important;
     442                        transform: translateY(-2px) !important;
     443                        box-shadow: 0 6px 18px rgba(220, 38, 38, 0.45) !important;
     444                }
     445                .portfoliox-dark-btn-demo {
     446                        background: #ffffff !important;
     447                        color: #4b5563 !important;
     448                        font-size: 13px !important;
     449                        font-weight: 600 !important;
     450                        padding: 8px 18px !important;
     451                        border-radius: 8px !important;
     452                        text-decoration: none !important;
     453                        border: 1px solid #d1d5db !important;
     454                        display: inline-flex !important;
     455                        align-items: center !important;
     456                        gap: 6px !important;
     457                        transition: all 0.2s ease !important;
     458                }
     459                .portfoliox-dark-btn-demo:hover {
     460                        background: #f9fafb !important;
     461                        color: #111827 !important;
     462                        border-color: #9ca3af !important;
     463                }
     464                .portfoliox-dark-btn-dismiss {
     465                        background: transparent !important;
     466                        border: none !important;
     467                        color: #9ca3af !important;
     468                        font-size: 12px !important;
     469                        cursor: pointer !important;
     470                        padding: 4px 6px !important;
     471                        text-decoration: underline !important;
     472                        transition: color 0.2s ease !important;
     473                }
     474                .portfoliox-dark-btn-dismiss:hover {
     475                        color: #4b5563 !important;
     476                }
     477                @media (max-width: 782px) {
     478                        .portfoliox-dark-pro-wrapper {
     479                                flex-direction: column !important;
     480                                align-items: flex-start !important;
     481                        }
     482                        .portfoliox-dark-pro-right {
     483                                align-items: flex-start !important;
     484                                width: 100% !important;
     485                        }
     486                        .portfoliox-dark-btn-cta {
     487                                width: 100% !important;
     488                                justify-content: center !important;
     489                        }
     490                }
    334491        </style>
    335492
    336         <div class="pxd-notice-wrap">
    337                 <div class="pxd-notice-title">
    338                         <span class="pxd-star">🌟</span>
    339                         <?php printf(esc_html__('Welcome to %s Experience!', 'portfoliox-dark'), esc_html($current_theme_name)); ?>
    340                 </div>
    341 
    342                 <div class="pxd-notice-desc">
    343                         <?php esc_html_e('Stop blending in — start landing clients.', 'portfoliox-dark'); ?>
    344                         <?php esc_html_e('Here is what PRO delivers to your portfolio:', 'portfoliox-dark'); ?>
    345                 </div>
    346 
    347                 <div class="pxd-notice-badges">
    348                         <span class="pxd-badge">✨ One-Click Demo Import</span>
    349                         <span class="pxd-badge">📈 Conversion-focused layouts</span>
    350                         <span class="pxd-badge">🧩 Advanced Portfolio Filters</span>
    351                         <span class="pxd-badge">🔥 Animated Home Text</span>
    352                         <span class="pxd-badge">💬 Dedicated Premium Support</span>
    353                 </div>
    354 
    355                 <div class="pxd-lifetime">
    356                         <span style="font-size:16px">🎯</span>
    357                         <div>
    358                                 <div class="pxd-lifetime-text">Buy Once, Get Lifetime Access</div>
    359                                 <div class="pxd-lifetime-sub">No recurring fees — one payment, yours forever.</div>
     493        <div class="portfoliox-dark-pro-notice-card">
     494                <div class="portfoliox-dark-pro-wrapper">
     495                        <div class="portfoliox-dark-pro-left">
     496                                <div class="portfoliox-dark-pro-header">
     497                                        <span class="portfoliox-dark-tag-pro"><?php esc_html_e('PRO UPGRADE', 'portfoliox-dark'); ?></span>
     498                                        <span class="portfoliox-dark-tag-deal">⚡ <?php esc_html_e('Special Offer: Now Only $21 - Price Dropped!', 'portfoliox-dark'); ?></span>
     499                                </div>
     500                                <h2 class="portfoliox-dark-pro-headline">
     501                                        <?php printf(esc_html__('Supercharge Your Dark Mode Portfolio & Agency Website with %s Pro!', 'portfoliox-dark'), esc_html($current_theme_name)); ?>
     502                                </h2>
     503                                <p class="portfoliox-dark-pro-desc">
     504                                        <?php esc_html_e('Unlock stunning dark mode portfolio showcases, sleek project sliders, video & audio portfolio items, lightning-fast Core Web Vitals speed, and 24/7 VIP priority support.', 'portfoliox-dark'); ?>
     505                                </p>
     506                                <div class="portfoliox-dark-pro-badges">
     507                                        <div class="portfoliox-dark-badge-item"><span>✓</span> <?php esc_html_e('1-Click Demo Import', 'portfoliox-dark'); ?></div>
     508                                        <div class="portfoliox-dark-badge-item"><span>✓</span> <?php esc_html_e('Sleek Dark Portfolio Grid', 'portfoliox-dark'); ?></div>
     509                                        <div class="portfoliox-dark-badge-item"><span>✓</span> <?php esc_html_e('Filterable Project Layouts', 'portfoliox-dark'); ?></div>
     510                                        <div class="portfoliox-dark-badge-item"><span>✓</span> <?php esc_html_e('Unlimited Colors & Layouts', 'portfoliox-dark'); ?></div>
     511                                        <div class="portfoliox-dark-badge-item"><span>✓</span> <?php esc_html_e('Remove Footer Credit', 'portfoliox-dark'); ?></div>
     512                                        <div class="portfoliox-dark-badge-item"><span>✓</span> <?php esc_html_e('24/7 VIP Priority Support', 'portfoliox-dark'); ?></div>
     513                                </div>
    360514                        </div>
    361                 </div>
    362 
    363                 <div class="pxd-notice-cta">
    364                         <a href="<?php echo $pro_link; ?>" target="_blank" class="pxd-btn pxd-btn--primary">
    365                                 🚀 <?php esc_html_e('Upgrade to PRO', 'portfoliox-dark'); ?>
    366                         </a>
    367                         <a href="<?php echo $demo_link; ?>" target="_blank" class="pxd-btn pxd-btn--secondary">
    368                                 <?php esc_html_e('👀 View Demo', 'portfoliox-dark'); ?>
    369                         </a>
    370                         <button class="pxd-btn pxd-btn--link btnend">
    371                                 <?php esc_html_e('Dismiss', 'portfoliox-dark'); ?>
    372                         </button>
     515                        <div class="portfoliox-dark-pro-right">
     516                                <a href="<?php echo esc_url($pro_link); ?>" target="_blank" class="portfoliox-dark-btn-cta">
     517                                        🚀 <?php esc_html_e('Upgrade to Pro for Only $21', 'portfoliox-dark'); ?>
     518                                </a>
     519                                <a href="<?php echo esc_url($demo_link); ?>" target="_blank" class="portfoliox-dark-btn-demo">
     520                                        👀 <?php esc_html_e('Live Demo & Features', 'portfoliox-dark'); ?>
     521                                </a>
     522                                <button class="portfoliox-dark-btn-dismiss btnend"><?php esc_html_e('Maybe Later', 'portfoliox-dark'); ?></button>
     523                        </div>
    373524                </div>
    374525        </div>
    … …  
    376527}
    377528
    378 
    379 
    380 //Admin notice
     529// Admin notice display
    381530function portfoliox_dark_new_optins_texts()
    382531{
    383         global $pagenow;
    384         $pxdinfo_date = get_option('portfoliox_dark_info_text1');
    385         if (!empty($pxdinfo_date) || $pagenow == 'themes.php') {
    386                 $clickhide = round((time() - strtotime($pxdinfo_date)) / 24 / 60 / 60);
    387                 if ($clickhide < 27) {
     532        $hide_date = get_option('portfoliox_dark_pro_textinfo_v114');
     533        if (!empty($hide_date)) {
     534                $clickhide = round((time() - strtotime($hide_date)) / 24 / 60 / 60);
     535                if ($clickhide < 25) {
    388536                        return;
    389537                }
    … …  
    391539
    392540?>
    393         <div class="mgadin-notice notice notice-success mgadin-theme-dashboard mgadin-theme-dashboard-notice mge is-dismissible meis-dismissible">
     541        <div class="mgadin-notice notice notice-success mgadin-theme-dashboard mgadin-theme-dashboard-notice mge is-dismissible meis-dismissible" style="padding:0; border:none; background:transparent;">
    394542                <?php portfoliox_dark_pnotice_output(); ?>
    395543        </div>
    396544<?php
    397 
    398545}
    399546add_action('admin_notices', 'portfoliox_dark_new_optins_texts');
    … …  
    401548function portfoliox_dark_new_optins_texts_init()
    402549{
    403         $install_date = get_option('portfoliox_dark_install_date');
     550        if (isset($_GET['xbnotice']) && $_GET['xbnotice'] == 1) {
     551                update_option('portfoliox_dark_pro_textinfo_v114', current_time('mysql'));
     552        }
     553        $install_date = get_option('portfoliox_dark_theme_install_date');
    404554        if (empty($install_date)) {
    405                 update_option('portfoliox_dark_install_date', current_time('mysql'));
    406         }
    407 
    408         if (isset($_GET['xbnotice']) && $_GET['xbnotice'] == 1) {
    409                 update_option('portfoliox_dark_info_text1', current_time('mysql'));
     555                update_option('portfoliox_dark_theme_install_date', current_time('mysql'));
    410556        }
    411557}
  • portfoliox-dark/1.0.14/inc/recommended-plugins.php

    r341891 r357072  
    22/**
    33 * Recommended plugins for PortfolioX Dark
    4  *
    5  * Core plugins (Posts Display, Magical Addons, Easy Share, Click To Top,
    6  * Password Protected, Elementor, Magical Blocks) come from the Magical Plugin
    7  * Activation library defaults. This file adds theme-specific extras.
    84 */
    95
    106function portfoliox_dark_magical_plugins($plugins) {
    117    $theme_plugins = array(
     8        'magical-posts-display' => array(
     9            'name'        => __('Posts Display', 'portfoliox-dark'),
     10            'slug'        => 'magical-posts-display',
     11            'file'        => 'magical-posts-display/magical-posts-display.php',
     12            'description' => __('Display posts in beautiful layouts.', 'portfoliox-dark'),
     13            'category'    => 'Content Display',
     14            'essential'   => false,
     15            'featured'    => true,
     16            'is_local'    => false,
     17        ),
     18        'magical-addons-for-elementor' => array(
     19            'name'        => __('Magical Addons', 'portfoliox-dark'),
     20            'slug'        => 'magical-addons-for-elementor',
     21            'file'        => 'magical-addons-for-elementor/magical-addons-for-elementor.php',
     22            'description' => __('Premium quality addons for Elementor page builder.', 'portfoliox-dark'),
     23            'category'    => 'Page Builder',
     24            'essential'   => false,
     25            'featured'    => true,
     26            'is_local'    => false,
     27        ),
     28        'magical-blocks' => array(
     29            'name'        => __('Magical Blocks', 'portfoliox-dark'),
     30            'slug'        => 'magical-blocks',
     31            'file'        => 'magical-blocks/magical-blocks.php',
     32            'description' => __('Premium quality blocks for WordPress gutenberg builder.', 'portfoliox-dark'),
     33            'category'    => 'Page Builder',
     34            'essential'   => false,
     35            'featured'    => true,
     36            'is_local'    => false,
     37        ),
    1238        'gallery-box' => array(
    1339            'name'        => __('Gallery Box', 'portfoliox-dark'),
    … …  
    1642            'description' => __('Beautiful gallery and lightbox plugin.', 'portfoliox-dark'),
    1743            'category'    => 'Media',
    18             'required'    => false,
     44            'essential'   => false,
    1945            'featured'    => true,
    2046            'is_local'    => false,
    2147        ),
    22         'ai-marketing-expert' => array(
    23             'name'        => __('AI Marketing Expert', 'portfoliox-dark'),
    24             'slug'        => 'ai-marketing-expert',
    25             'file'        => 'ai-marketing-expert/ai-marketing-expert.php',
    26             'description' => __('AI-powered marketing suite with email marketing, content generator, SEO analyzer, social media, and chatbot.', 'portfoliox-dark'),
    27             'category'    => 'Marketing',
    28             'required'    => false,
    29             'timed_auto'  => true,
     48        'click-to-top' => array(
     49            'name'        => __('Click To Top', 'portfoliox-dark'),
     50            'slug'        => 'click-to-top',
     51            'file'        => 'click-to-top/click-to-top.php',
     52            'description' => __('One-click scroll to top button.', 'portfoliox-dark'),
     53            'category'    => 'Utility',
     54            'essential'   => false,
    3055            'featured'    => true,
    3156            'is_local'    => false,
    … …  
    4065            'description' => __('Display WooCommerce products in beautiful layouts.', 'portfoliox-dark'),
    4166            'category'    => 'eCommerce',
    42             'required'    => false,
     67            'essential'   => false,
    4368            'featured'    => true,
    4469            'is_local'    => false,
    … …  
    5378 * AI Marketing Expert success notice
    5479 */
     80if (!function_exists('portfoliox_dark_ai_marketing_notice')) :
    5581function portfoliox_dark_ai_marketing_notice() {
    5682    if (!is_plugin_active('ai-marketing-expert/ai-marketing-expert.php')) {
    … …  
    91117}
    92118add_action('admin_notices', 'portfoliox_dark_ai_marketing_notice');
     119endif;
  • portfoliox-dark/1.0.14/libs/magical-plugin-activation/assets/css/admin-plugins.css

    r306496 r357072  
    1 /* Shop Toolkit Pro Plugin Recommendations Admin Styles */
    2 
     1/* Magical Plugin Activation Admin Styles */
    32.magical-plugin-activation-plugins {
    43    padding: 20px 0;
    54    max-width: 1400px;
    65}
    7 
    86.magical-plugin-activation-plugins .description {
    97    font-size: 14px;
    … …  
    1614    border-radius: 4px;
    1715}
    18 
    19 /* Filter Tabs */
    2016.plugin-filter-tabs {
    2117    margin-bottom: 30px;
    … …  
    2925    box-shadow: 0 1px 3px rgba(0,0,0,0.1);
    3026}
    31 
    3227.filter-tab {
    3328    background: none;
    … …  
    4338    position: relative;
    4439}
    45 
    4640.filter-tab:hover {
    4741    color: #0073aa;
    … …  
    4943    border-bottom-color: #0073aa;
    5044}
    51 
    5245.filter-tab.active {
    5346    color: #0073aa;
    … …  
    5750    box-shadow: 0 -2px 5px rgba(0,0,0,0.1);
    5851}
    59 
    60 /* Plugins Grid */
    6152.plugins-grid {
    6253    display: grid;
    … …  
    6960    box-shadow: 0 2px 8px rgba(0,0,0,0.1);
    7061}
    71 
    7262.plugin-card {
    7363    background: #fff;
    … …  
    8171    width: 100%;
    8272}
    83 
    8473.plugin-card:hover {
    8574    border-color: #0073aa;
    … …  
    8776    transform: translateY(-4px);
    8877}
    89 
    9078.plugin-card.featured {
    9179    border-color: #00a32a;
    … …  
    9381    background: linear-gradient(135deg, #fff 0%, #f8fff9 100%);
    9482}
    95 
    9683.plugin-card.featured::before {
    9784    content: '';
    … …  
    10592    animation: featured-shimmer 3s ease-in-out infinite;
    10693}
    107 
    10894@keyframes featured-shimmer {
    10995    0%, 100% { background-position: 200% 0; }
    11096    50% { background-position: -200% 0; }
    11197}
    112 
    113 /* Featured Badge */
    11498.featured-badge {
    11599    position: absolute;
    … …  
    126110    letter-spacing: 0.5px;
    127111}
    128 
    129 /* Required Plugin Badge */
    130 .plugin-card .required-badge {
     112.essential-badge {
    131113    position: absolute;
    132114    top: 10px;
    … …  
    144126}
    145127
    146 /* Plugin Card Required Styling */
    147 .plugin-card[data-required="1"] {
     128.plugin-card[data-essential="1"] {
    148129    border: 2px solid #d63638;
    149130    box-shadow: 0 4px 12px rgba(214, 54, 56, 0.15);
    150131}
    151 
    152 .plugin-card[data-required="1"] .plugin-header h3 {
     132.plugin-card[data-essential="1"] .plugin-header h3 {
    153133    color: #d63638;
    154134    font-weight: 600;
    155135}
    156 
    157 /* Filter Tab for Required */
    158 .filter-tab[data-filter="required"] {
     136.filter-tab[data-filter="essential"] {
    159137    background: #fff2f2;
    160138    border-color: #d63638;
    161139    color: #d63638;
    162140}
    163 
    164 .filter-tab[data-filter="required"].active {
     141.filter-tab[data-filter="essential"].active {
    165142    background: #d63638;
    166143    color: white;
    167144}
    168 
    169 /* Plugin Header */
    170145.plugin-header {
    171146    margin-bottom: 18px;
    … …  
    173148    padding-bottom: 15px;
    174149}
    175 
    176150.plugin-header h3 {
    177151    margin: 0 0 8px 0;
    … …  
    182156    letter-spacing: -0.01em;
    183157}
    184 
    185158.plugin-category {
    186159    display: inline-block;
    … …  
    195168    box-shadow: 0 1px 3px rgba(0,0,0,0.1);
    196169}
    197 
    198 /* Category-specific colors */
    199 .plugin-category {
    200     background: #f0f0f1;
    201     color: #50575e;
    202 }
    203 
    204 /* Plugin Description */
    205170.plugin-description {
    206171    margin-bottom: 25px;
    207172    min-height: 60px;
    208173}
    209 
    210174.plugin-description p {
    211175    margin: 0;
    … …  
    214178    font-size: 14px;
    215179}
    216 
    217 /* Plugin Actions */
    218180.plugin-actions {
    219181    display: flex;
    … …  
    224186    border-top: 1px solid #f0f0f1;
    225187}
    226 
    227188.plugin-actions .button {
    228189    min-width: 100px;
    … …  
    234195    text-transform: none;
    235196}
    236 
    237197.plugin-actions .button-primary {
    238198    background: linear-gradient(135deg, #0073aa 0%, #005a87 100%);
    … …  
    240200    box-shadow: 0 2px 4px rgba(0,115,170,0.3);
    241201}
    242 
    243202.plugin-actions .button-primary:hover {
    244203    background: linear-gradient(135deg, #005a87 0%, #004866 100%);
    … …  
    246205    box-shadow: 0 4px 8px rgba(0,115,170,0.4);
    247206}
    248 
    249207.plugin-actions .button.disabled {
    250208    background: linear-gradient(135deg, #f0f0f1 0%, #e8e8e9 100%);
    … …  
    253211    border-color: #ddd;
    254212}
    255 
    256 /* Plugin Status */
    257213.plugin-status {
    258214    font-size: 12px;
    … …  
    264220    box-shadow: 0 1px 3px rgba(0,0,0,0.1);
    265221}
    266 
    267222.plugin-status.status-active {
    268223    background: linear-gradient(135deg, #d1e7dd 0%, #c3e6cb 100%);
    … …  
    270225    border: 1px solid #badbcc;
    271226}
    272 
    273227.plugin-status.status-inactive {
    274228    background: linear-gradient(135deg, #fff3cd 0%, #ffeaa7 100%);
    … …  
    276230    border: 1px solid #f1c40f;
    277231}
    278 
    279232.plugin-status.status-not-installed {
    280233    background: linear-gradient(135deg, #f8d7da 0%, #f5c6cb 100%);
    … …  
    282235    border: 1px solid #f1556c;
    283236}
    284 
    285 /* Update status styles */
    286237.plugin-status.status-needs-update {
    287238    background: linear-gradient(135deg, #ffeaa7 0%, #fdcb6e 100%);
    … …  
    290241    animation: updatePulse 2s ease-in-out infinite;
    291242}
    292 
    293243.plugin-status.status-inactive-needs-update {
    294244    background: linear-gradient(135deg, #fab1a0 0%, #e17055 100%);
    … …  
    297247    animation: updatePulse 2s ease-in-out infinite;
    298248}
    299 
    300249@keyframes updatePulse {
    301     0%, 100% {
    302         transform: scale(1);
    303         opacity: 1;
    304     }
    305     50% {
    306         transform: scale(1.05);
    307         opacity: 0.8;
    308     }
    309 }
    310 
    311 /* Update button styles */
     250    0%, 100% { transform: scale(1); opacity: 1; }
     251    50% { transform: scale(1.05); opacity: 0.8; }
     252}
    312253.button.update-plugin {
    313254    background: linear-gradient(135deg, #fdcb6e 0%, #e17055 100%) !important;
    … …  
    317258    border-radius: 6px !important;
    318259    box-shadow: 0 2px 4px rgba(253, 203, 110, 0.3) !important;
    319     position: relative !important;
    320260    overflow: hidden !important;
    321261}
    322 
    323262.button.update-plugin:hover {
    324263    background: linear-gradient(135deg, #e17055 0%, #d63031 100%) !important;
    … …  
    326265    box-shadow: 0 4px 8px rgba(253, 203, 110, 0.4) !important;
    327266}
    328 
    329 .button.update-plugin::before {
    330     content: '⚡';
    331     margin-right: 5px;
    332 }
    333 
    334 /* Version info styles */
    335 .version-info {
    336     display: block;
    337     margin-top: 5px;
    338     color: #666;
    339     font-size: 11px;
    340     line-height: 1.3;
    341     opacity: 0.8;
    342 }
    343 
    344 .plugin-card[data-status="needs-update"] .version-info,
    345 .plugin-card[data-status="inactive-needs-update"] .version-info {
    346     color: #d63031;
    347     font-weight: 600;
    348 }
    349 
    350 /* Local plugin badge */
    351267.local-plugin-badge {
    352268    position: absolute;
    … …  
    364280    box-shadow: 0 2px 4px rgba(108, 92, 231, 0.3);
    365281}
    366 
    367 /* Plugin card with local plugin styling */
    368282.plugin-card[data-local="1"] {
    369283    border: 2px solid #6c5ce7;
    … …  
    371285    box-shadow: 0 4px 12px rgba(108, 92, 231, 0.15);
    372286}
    373 
    374287.plugin-card[data-local="1"] .plugin-header h3 {
    375288    color: #6c5ce7;
    376289    font-weight: 600;
    377290}
    378 
    379 /* Update available notice */
    380 .update-notice {
    381     background: linear-gradient(135deg, #fff3cd 0%, #ffeaa7 100%);
    382     border: 1px solid #ffeaa7;
    383     border-radius: 8px;
    384     padding: 15px;
    385     margin: 20px 0;
    386     box-shadow: 0 2px 8px rgba(253, 203, 110, 0.2);
    387 }
    388 
    389 .update-notice h3 {
    390     margin: 0 0 10px 0;
    391     color: #d63031;
    392     font-size: 16px;
    393     display: flex;
    394     align-items: center;
    395     gap: 8px;
    396 }
    397 
    398 .update-notice h3::before {
    399     content: '⚠️';
    400     font-size: 18px;
    401 }
    402 
    403 .update-notice p {
    404     margin: 0;
    405     color: #856404;
    406     line-height: 1.5;
    407 }
    408 
    409 /* Loading States */
     291.version-info {
     292    display: block;
     293    margin-top: 5px;
     294    color: #666;
     295    font-size: 11px;
     296    line-height: 1.3;
     297    opacity: 0.8;
     298}
    410299.button.loading {
    411300    position: relative;
    … …  
    414303    overflow: hidden;
    415304}
    416 
    417305.button.loading::after {
    418306    content: '';
    … …  
    428316    animation: button-loading 1s linear infinite;
    429317}
    430 
    431318@keyframes button-loading {
    432     to {
    433         transform: rotate(360deg);
    434     }
    435 }
    436 
    437 /* Filter States */
    438 .plugin-card.hidden {
    439     display: none;
    440 }
    441 
    442 /* Admin Notice */
    443 .magical-plugin-activation-pro-plugin-notice {
    444     position: relative;
    445     border: none !important;
    446     background: linear-gradient(135deg, #fff 0%, #f8f9ff 100%) !important;
    447     border-radius: 12px !important;
    448     box-shadow: 0 4px 20px rgba(34, 113, 177, 0.12) !important;
    449     padding: 0 !important;
    450     margin: 20px 0 !important;
    451     overflow: hidden;
    452 }
    453 
    454 .magical-plugin-activation-pro-plugin-notice::before {
    455     content: '';
    456     position: absolute;
    457     top: 0;
    458     left: 0;
    459     right: 0;
    460     height: 4px;
    461     background: linear-gradient(90deg, #2271b1 0%, #135e96 50%, #2271b1 100%);
    462     background-size: 200% 100%;
    463     animation: recommendedShimmer 3s ease-in-out infinite;
    464 }
    465 
    466 @keyframes recommendedShimmer {
    467     0%, 100% { background-position: 200% 0; }
    468     50% { background-position: -200% 0; }
    469 }
    470 
    471 .magical-plugin-activation-pro-plugin-notice > div {
    472     padding: 20px 25px !important;
    473     display: flex !important;
    474     align-items: center !important;
    475     gap: 20px !important;
    476     margin: 0 !important;
    477 }
    478 
    479 .magical-plugin-activation-pro-plugin-notice h3 {
    480     color: #2271b1 !important;
    481     font-size: 18px !important;
    482     font-weight: 600 !important;
    483     margin: 0 0 8px 0 !important;
    484     display: flex !important;
    485     align-items: center !important;
    486     gap: 8px !important;
    487 }
    488 
    489 .magical-plugin-activation-pro-plugin-notice h3::before {
    490     content: '⚡';
    491     font-size: 20px;
    492     filter: hue-rotate(200deg);
    493 }
    494 
    495 .magical-plugin-activation-pro-plugin-notice p {
    496     color: #3c434a !important;
    497     font-size: 14px !important;
    498     line-height: 1.5 !important;
    499     margin: 0 0 15px 0 !important;
    500 }
    501 
    502 .magical-plugin-activation-pro-plugin-notice .button {
    503     background: linear-gradient(135deg, #2271b1 0%, #135e96 100%) !important;
    504     border: none !important;
    505     color: #fff !important;
    506     font-weight: 600 !important;
    507     border-radius: 8px !important;
    508     padding: 10px 20px !important;
    509     font-size: 14px !important;
    510     text-decoration: none !important;
    511     transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1) !important;
    512     box-shadow: 0 2px 8px rgba(34, 113, 177, 0.3) !important;
    513     position: relative !important;
    514     overflow: hidden !important;
    515 }
    516 
    517 .magical-plugin-activation-pro-plugin-notice .button::before {
    518     content: '';
    519     position: absolute;
    520     top: 0;
    521     left: -100%;
    522     width: 100%;
    523     height: 100%;
    524     background: linear-gradient(90deg, transparent, rgba(255,255,255,0.2), transparent);
    525     transition: left 0.5s;
    526 }
    527 
    528 .magical-plugin-activation-pro-plugin-notice .button:hover::before {
    529     left: 100%;
    530 }
    531 
    532 .magical-plugin-activation-pro-plugin-notice .button:hover {
    533     background: linear-gradient(135deg, #135e96 0%, #0f4a75 100%) !important;
    534     transform: translateY(-2px) !important;
    535     box-shadow: 0 4px 12px rgba(34, 113, 177, 0.4) !important;
    536 }
    537 
    538 .magical-plugin-activation-pro-plugin-notice .button:active {
    539     transform: translateY(0) !important;
    540 }
    541 
    542 .magical-plugin-activation-pro-plugin-notice .button-secondary {
    543     background: rgba(34, 113, 177, 0.1) !important;
    544     color: #2271b1 !important;
    545     border: 2px solid rgba(34, 113, 177, 0.2) !important;
    546     box-shadow: none !important;
    547 }
    548 
    549 .magical-plugin-activation-pro-plugin-notice .button-secondary:hover {
    550     background: rgba(34, 113, 177, 0.15) !important;
    551     border-color: rgba(34, 113, 177, 0.3) !important;
    552     transform: translateY(-1px) !important;
    553 }
    554 
    555 .magical-plugin-activation-pro-plugin-notice .notice-dismiss {
    556     top: 15px !important;
    557     right: 15px !important;
    558     color: #2271b1 !important;
    559     opacity: 0.6 !important;
    560     font-size: 18px !important;
    561 }
    562 
    563 .magical-plugin-activation-pro-plugin-notice .notice-dismiss:hover {
    564     opacity: 1 !important;
    565     color: #135e96 !important;
    566 }
    567 
    568 /* Plugin icon in notice */
    569 .magical-plugin-activation-pro-plugin-notice .plugin-icon-recomend {
    570     font-size: 48px;
    571     color: #2271b1;
    572     opacity: 0.15;
    573     min-width: 60px;
    574     text-align: center;
    575 }
    576 
    577 /* Success/Error Messages */
    578 .plugin-message {
    579     position: absolute;
    580     top: 15px;
    581     right: 15px;
    582     background: #00a32a;
    583     color: white;
    584     padding: 8px 12px;
    585     border-radius: 6px;
    586     font-size: 12px;
    587     font-weight: 600;
    588     opacity: 0;
    589     transform: translateY(-10px) scale(0.9);
    590     transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
    591     box-shadow: 0 4px 12px rgba(0,163,42,0.3);
    592     z-index: 10;
    593 }
    594 
    595 .plugin-message.show {
    596     opacity: 1;
    597     transform: translateY(0) scale(1);
    598 }
    599 
    600 .plugin-message.error {
    601     background: #d63638;
    602     box-shadow: 0 4px 12px rgba(214,54,56,0.3);
    603 }
    604 
    605 /* Install Required Plugins Button */
    606 #install-required-plugins {
    607     animation: pulse 2s infinite;
    608 }
    609 
    610 @keyframes pulse {
    611     0% { transform: scale(1); }
    612     50% { transform: scale(1.05); }
    613     100% { transform: scale(1); }
    614 }
    615 
    616 #install-required-plugins:hover {
    617     animation: none;
    618     transform: scale(1.05);
    619 }
    620 
    621 /* Progress indicator for bulk install */
    622 .bulk-install-progress {
    623     margin: 15px 0;
    624     padding: 15px;
    625     background: linear-gradient(135deg, #f8f9fa 0%, #e9ecef 100%);
    626     border-radius: 8px;
    627     border: 1px solid #dee2e6;
    628     box-shadow: 0 2px 4px rgba(0,0,0,0.1);
    629     display: none;
    630 }
    631 
    632 .bulk-install-progress.active {
    633     display: block;
    634     animation: slideIn 0.3s ease-out;
    635 }
    636 
    637 @keyframes slideIn {
    638     from {
    639         opacity: 0;
    640         transform: translateY(-10px);
    641     }
    642     to {
    643         opacity: 1;
    644         transform: translateY(0);
    645     }
    646 }
    647 
    648 .progress-bar {
    649     height: 12px;
    650     background: #e9ecef;
    651     border-radius: 6px;
    652     overflow: hidden;
    653     margin-bottom: 10px;
    654     position: relative;
    655     box-shadow: inset 0 1px 2px rgba(0,0,0,0.1);
    656 }
    657 
    658 .progress-bar::before {
    659     content: '';
    660     position: absolute;
    661     top: 0;
    662     left: 0;
    663     right: 0;
    664     height: 50%;
    665     background: linear-gradient(to bottom, rgba(255,255,255,0.3), transparent);
    666     border-radius: 6px 6px 0 0;
    667 }
    668 
    669 .progress-fill {
    670     height: 100%;
    671     background: linear-gradient(45deg, #0073aa 25%, #005a87 25%, #005a87 50%, #0073aa 50%, #0073aa 75%, #005a87 75%, #005a87);
    672     background-size: 20px 20px;
    673     transition: width 0.8s cubic-bezier(0.25, 0.46, 0.45, 0.94);
    674     width: 0%;
    675     position: relative;
    676     border-radius: 6px;
    677     animation: progressStripes 1s linear infinite;
    678 }
    679 
    680 @keyframes progressStripes {
    681     0% {
    682         background-position: 0 0;
    683     }
    684     100% {
    685         background-position: 20px 0;
    686     }
    687 }
    688 
    689 .progress-fill::after {
    690     content: '';
    691     position: absolute;
    692     top: 0;
    693     left: 0;
    694     right: 0;
    695     height: 100%;
    696     background: linear-gradient(to right, rgba(255,255,255,0.2), transparent, rgba(255,255,255,0.2));
    697     border-radius: 6px;
    698     animation: progressGlow 2s ease-in-out infinite;
    699 }
    700 
    701 @keyframes progressGlow {
    702     0%, 100% {
    703         opacity: 0;
    704     }
    705     50% {
    706         opacity: 1;
    707     }
    708 }
    709 
    710 .progress-text {
    711     font-size: 13px;
    712     color: #495057;
    713     text-align: center;
    714     font-weight: 500;
    715     margin: 0;
    716 }
    717 
    718 /* Plugin Update Notice */
    719 .magical-plugin-activation-pro-update-notice {
    720     position: relative;
    721     border: 1px solid #d39e00;
    722     border-left: 4px solid #d39e00;
    723     padding: 12px;
    724     margin: 5px 15px 20px 0;
    725     background: #fff8e1;
    726     border-radius: 4px;
    727     box-shadow: 0 2px 4px rgba(0,0,0,0.1);
    728 }
    729 
    730 .magical-plugin-activation-pro-update-notice .plugin-update-content {
    731     display: flex;
    732     align-items: flex-start;
    733     gap: 20px;
    734 }
    735 
    736 .magical-plugin-activation-pro-update-notice .plugin-update-content h3 {
    737     margin: 0 0 10px 0;
    738     font-size: 18px;
    739     font-weight: 600;
    740     color: #d39e00;
    741 }
    742 
    743 .magical-plugin-activation-pro-update-notice .plugin-update-content p {
    744     margin: 0 0 15px 0;
    745     font-size: 14px;
    746     line-height: 1.5;
    747     color: #5c5c5c;
    748 }
    749 
    750 .magical-plugin-activation-pro-update-notice .plugin-icon-recomend {
    751     font-size: 32px;
    752     opacity: 0.8;
    753     min-width: 40px;
    754     text-align: center;
    755 }
    756 
    757 .plugin-update-list {
    758     margin: 15px 0;
    759     padding: 0;
    760     list-style: none;
    761 }
    762 
    763 .plugin-update-item {
    764     display: flex;
    765     align-items: center;
    766     gap: 10px;
    767     margin-bottom: 10px;
    768     padding: 10px;
    769     background: #fff;
    770     border: 1px solid #e0e0e0;
    771     border-radius: 4px;
    772     font-size: 13px;
    773     flex-wrap: wrap;
    774 }
    775 
    776 .plugin-update-item strong {
    777     color: #333;
    778     font-weight: 600;
    779     flex-shrink: 0;
    780 }
    781 
    782 .plugin-update-item .local-plugin-badge {
    783     background: #2271b1;
    784     color: white;
    785     padding: 2px 6px;
    786     border-radius: 3px;
    787     font-size: 11px;
    788     font-weight: 500;
    789     text-transform: uppercase;
    790     letter-spacing: 0.5px;
    791 }
    792 
    793 .plugin-update-item .version-info {
    794     color: #666;
    795     font-size: 12px;
    796     margin-left: auto;
    797 }
    798 
    799 .plugin-update-item .button {
    800     margin-left: 10px;
    801     padding: 4px 8px;
    802     font-size: 12px;
    803     height: auto;
    804     line-height: 1.2;
    805 }
    806 
    807 /* Update button styles */
    808 .update-plugin {
    809     background: #d39e00;
    810     color: white;
    811     border: none;
    812     padding: 8px 16px;
    813     border-radius: 4px;
    814     cursor: pointer;
    815     font-weight: 500;
    816     text-decoration: none;
    817     transition: all 0.3s ease;
    818     position: relative;
    819     overflow: hidden;
    820 }
    821 
    822 .update-plugin:hover {
    823     background: #b8860b;
    824     transform: translateY(-2px);
    825     box-shadow: 0 4px 8px rgba(211, 158, 0, 0.3);
    826 }
    827 
    828 .update-plugin:active {
    829     transform: translateY(0);
    830 }
    831 
    832 .update-plugin:disabled,
    833 .update-plugin.loading {
    834     opacity: 0.6;
    835     cursor: not-allowed;
    836     pointer-events: none;
    837 }
    838 
    839 .update-plugin.loading::after {
    840     content: '';
    841     position: absolute;
    842     top: 0;
    843     left: -100%;
    844     width: 100%;
    845     height: 100%;
    846     background: linear-gradient(90deg, transparent, rgba(255,255,255,0.3), transparent);
    847     animation: button-loading 1.5s ease-in-out infinite;
    848 }
    849 
    850 @keyframes button-loading {
    851     0% { left: -100%; }
    852     100% { left: 100%; }
    853 }
    854 
    855 /* Update All Plugins Button */
    856 #update-all-plugins {
    857     background: #d39e00;
    858     color: white;
    859     border: none;
    860     padding: 10px 20px;
    861     border-radius: 4px;
    862     cursor: pointer;
    863     font-weight: 600;
    864     text-decoration: none;
    865     transition: all 0.3s ease;
    866     display: inline-flex;
    867     align-items: center;
    868     gap: 8px;
    869 }
    870 
    871 #update-all-plugins:hover {
    872     background: #b8860b;
    873     transform: translateY(-2px);
    874     box-shadow: 0 4px 12px rgba(211, 158, 0, 0.3);
    875 }
    876 
    877 #update-all-plugins:active {
    878     transform: translateY(0);
    879 }
    880 
    881 #update-all-plugins:before {
    882     content: "🔄";
    883     font-size: 14px;
    884 }
    885 
    886 /* Plugin status indicators for updates */
    887 .plugin-status.status-needs-update,
    888 .plugin-status.status-inactive-needs-update {
    889     color: #d39e00;
    890     font-weight: 600;
    891     background: #fff8e1;
    892     padding: 4px 8px;
    893     border-radius: 3px;
    894     border: 1px solid #d39e00;
    895 }
    896 
    897 .plugin-status.status-needs-update::before,
    898 .plugin-status.status-inactive-needs-update::before {
    899     content: "🔄";
    900     margin-right: 4px;
    901 }
    902 
    903 /* Version info styling */
    904 .plugin-card .version-info {
    905     display: block;
    906     margin-top: 8px;
    907     color: #666;
    908     font-size: 12px;
    909     line-height: 1.3;
    910 }
    911 
    912 .plugin-card .version-info strong {
    913     color: #333;
    914 }
    915 
    916 /* Update available badge */
    917 .plugin-card .update-available {
    918     position: absolute;
    919     top: -5px;
    920     right: -5px;
    921     background: #d39e00;
    922     color: white;
    923     padding: 4px 8px;
    924     border-radius: 12px;
    925     font-size: 11px;
    926     font-weight: 600;
    927     text-transform: uppercase;
    928     letter-spacing: 0.5px;
    929     box-shadow: 0 2px 4px rgba(0,0,0,0.2);
    930     z-index: 10;
    931 }
    932 
    933 /* Responsive design for update notice */
     319    to { transform: rotate(360deg); }
     320}
     321.plugin-card.hidden { display: none; }
    934322@media (max-width: 782px) {
    935     .magical-plugin-activation-pro-update-notice .plugin-update-content {
    936         flex-direction: column;
    937         gap: 15px;
    938     }
    939    
    940     .plugin-update-item {
    941         flex-direction: column;
    942         align-items: flex-start;
    943         gap: 8px;
    944     }
    945    
    946     .plugin-update-item .version-info {
    947         margin-left: 0;
    948     }
    949    
    950     .plugin-update-item .button {
    951         margin-left: 0;
    952         margin-top: 8px;
    953         align-self: flex-start;
    954     }
    955 }
    956 
    957 /* Responsive Design */
    958 @media (max-width: 1200px) {
    959     .plugins-grid {
    960         grid-template-columns: repeat(auto-fill, minmax(320px, 1fr));
    961         gap: 20px;
    962     }
    963 }
    964 
    965 @media (max-width: 782px) {
    966     .magical-plugin-activation-plugins {
    967         padding: 10px 0;
    968     }
    969    
    970     .plugins-grid {
    971         grid-template-columns: 1fr;
    972         gap: 15px;
    973         padding: 15px;
    974     }
    975    
    976     .plugin-filter-tabs {
    977         padding: 8px;
    978         gap: 3px;
    979     }
    980    
    981     .filter-tab {
    982         flex: 1;
    983         min-width: auto;
    984         text-align: center;
    985         padding: 10px 8px;
    986         font-size: 11px;
    987         margin-right: 0;
    988     }
    989    
    990     .plugin-card {
    991         padding: 20px;
    992     }
    993    
    994     .plugin-actions {
    995         flex-direction: column;
    996         align-items: stretch;
    997         gap: 10px;
    998     }
    999    
    1000     .plugin-actions .button {
    1001         width: 100%;
    1002     }
    1003    
    1004     .magical-plugin-activation-pro-plugin-notice p {
    1005         flex-direction: column;
    1006         align-items: flex-start;
    1007         gap: 10px;
    1008     }
    1009    
    1010     .magical-plugin-activation-pro-plugin-notice .button {
    1011         margin-left: 0;
    1012         align-self: stretch;
    1013     }
    1014 }
    1015 
    1016 /* Responsive improvements for recommended notice */
    1017 @media (max-width: 768px) {
    1018     .magical-plugin-activation-pro-plugin-notice > div {
    1019         flex-direction: column !important;
    1020         text-align: center !important;
    1021         gap: 15px !important;
    1022     }
    1023    
    1024     .magical-plugin-activation-pro-plugin-notice > div > div:first-child {
    1025         order: 2;
    1026     }
    1027    
    1028     .magical-plugin-activation-pro-plugin-notice .plugin-icon-recomend {
    1029         order: 1;
    1030         font-size: 36px !important;
    1031     }
    1032    
    1033     .magical-plugin-activation-pro-plugin-notice > div > div:first-child > div {
    1034         justify-content: center !important;
    1035     }
    1036    
    1037     .bulk-install-progress {
    1038         padding: 12px !important;
    1039         margin: 10px 0 !important;
    1040     }
    1041    
    1042     .progress-text {
    1043         font-size: 12px !important;
    1044     }
    1045 }
    1046 
    1047 /* Animation for when plugins are successfully installed */
    1048 @keyframes success-pulse {
    1049     0%, 100% {
    1050         transform: scale(1);
    1051         opacity: 1;
    1052     }
    1053     50% {
    1054         transform: scale(1.05);
    1055         opacity: 0.8;
    1056     }
    1057 }
    1058 
    1059 .magical-plugin-activation-pro-plugin-notice.success {
    1060     animation: success-pulse 0.6s ease-in-out;
    1061 }
    1062 
    1063 /* Loading state for buttons */
    1064 .magical-plugin-activation-pro-plugin-notice .button.loading {
    1065     position: relative;
    1066     color: transparent !important;
    1067     pointer-events: none;
    1068     overflow: hidden;
    1069 }
    1070 
    1071 .magical-plugin-activation-pro-plugin-notice .button.loading::after {
    1072     content: '';
    1073     position: absolute;
    1074     top: 50%;
    1075     left: 50%;
    1076     width: 16px;
    1077     height: 16px;
    1078     margin: -8px 0 0 -8px;
    1079     border: 2px solid rgba(255,255,255,0.3);
    1080     border-radius: 50%;
    1081     border-top-color: #fff;
    1082     animation: button-loading 1s linear infinite;
    1083 }
    1084 
    1085 /* Bulk Update Progress */
    1086 .bulk-update-progress {
    1087     margin-top: 15px;
    1088     padding: 15px;
    1089     background: #fff;
    1090     border: 1px solid #ddd;
    1091     border-radius: 6px;
    1092     box-shadow: 0 2px 4px rgba(0,0,0,0.1);
    1093     opacity: 0;
    1094     transform: translateY(-10px);
    1095     transition: all 0.3s ease;
    1096 }
    1097 
    1098 .bulk-update-progress.active {
    1099     opacity: 1;
    1100     transform: translateY(0);
    1101 }
    1102 
    1103 .bulk-update-progress .progress-bar {
    1104     height: 8px;
    1105     background: #e0e0e0;
    1106     border-radius: 4px;
    1107     overflow: hidden;
    1108     margin-bottom: 10px;
    1109 }
    1110 
    1111 .bulk-update-progress .progress-fill {
    1112     height: 100%;
    1113     background: linear-gradient(90deg, #d39e00, #f1c40f);
    1114     border-radius: 4px;
    1115     transition: width 0.3s ease;
    1116     position: relative;
    1117 }
    1118 
    1119 .bulk-update-progress .progress-fill::after {
    1120     content: '';
    1121     position: absolute;
    1122     top: 0;
    1123     left: 0;
    1124     width: 100%;
    1125     height: 100%;
    1126     background: linear-gradient(90deg, transparent, rgba(255,255,255,0.3), transparent);
    1127     animation: progress-shimmer 1.5s ease-in-out infinite;
    1128 }
    1129 
    1130 @keyframes progress-shimmer {
    1131     0% { transform: translateX(-100%); }
    1132     100% { transform: translateX(100%); }
    1133 }
    1134 
    1135 .bulk-update-progress .progress-text {
    1136     font-size: 13px;
    1137     color: #666;
    1138     text-align: center;
    1139     font-weight: 500;
    1140 }
    1141 
    1142 /* Improved focus states for accessibility */
    1143 .filter-tab:focus,
    1144 .plugin-actions .button:focus {
    1145     outline: 2px solid #0073aa;
    1146     outline-offset: 2px;
    1147 }
    1148 
    1149 /* Loading skeleton effect */
    1150 .plugin-card.loading {
    1151     position: relative;
    1152     overflow: hidden;
    1153 }
    1154 
    1155 .plugin-card.loading::before {
    1156     content: '';
    1157     position: absolute;
    1158     top: 0;
    1159     left: -100%;
    1160     width: 100%;
    1161     height: 100%;
    1162     background: linear-gradient(90deg, transparent, rgba(255,255,255,0.4), transparent);
    1163     animation: loading-shimmer 1.5s ease-in-out infinite;
    1164 }
    1165 
    1166 @keyframes loading-shimmer {
    1167     0% { left: -100%; }
    1168     100% { left: 100%; }
    1169 }
    1170 
    1171 /* Plugin Notices */
    1172 .magical-plugin-activation-pro-required-notice,
    1173 .magical-plugin-activation-pro-recommended-notice,
    1174 .magical-plugin-activation-pro-update-notice {
    1175     border-radius: 8px;
    1176     box-shadow: 0 2px 4px rgba(0,0,0,0.1);
    1177     margin: 20px 0;
    1178     animation: slideInFromTop 0.3s ease-out;
    1179 }
    1180 
    1181 .magical-plugin-activation-pro-required-notice {
    1182     border-left: 4px solid #dc3232;
    1183 }
    1184 
    1185 .magical-plugin-activation-pro-recommended-notice {
    1186     border-left: 4px solid #0073aa;
    1187 }
    1188 
    1189 .magical-plugin-activation-pro-update-notice {
    1190     border-left: 4px solid #ffb900;
    1191 }
    1192 
    1193 .plugin-recommended-content,
    1194 .plugin-update-content {
    1195     display: flex;
    1196     align-items: center;
    1197     gap: 20px;
    1198     padding: 10px 0;
    1199 }
    1200 
    1201 .plugin-recommended-content .plugin-icon-recomend,
    1202 .plugin-update-content .plugin-icon-recomend {
    1203     font-size: 24px;
    1204     opacity: 0.8;
    1205 }
    1206 
    1207 .plugin-recommended-content h3,
    1208 .plugin-update-content h3 {
    1209     margin: 0 0 10px 0;
    1210     color: #23282d;
    1211     font-size: 16px;
    1212 }
    1213 
    1214 .plugin-recommended-content p,
    1215 .plugin-update-content p {
    1216     margin: 0 0 15px 0;
    1217     color: #646970;
    1218     line-height: 1.5;
    1219 }
    1220 
    1221 @keyframes slideInFromTop {
    1222     from {
    1223         transform: translateY(-20px);
    1224         opacity: 0;
    1225     }
    1226     to {
    1227         transform: translateY(0);
    1228         opacity: 1;
    1229     }
    1230 }
     323    .plugins-grid { grid-template-columns: 1fr; gap: 15px; padding: 15px; }
     324    .filter-tab { flex: 1; text-align: center; padding: 10px 8px; font-size: 11px; }
     325    .plugin-card { padding: 20px; }
     326    .plugin-actions { flex-direction: column; align-items: stretch; gap: 10px; }
     327    .plugin-actions .button { width: 100%; }
     328}
  • portfoliox-dark/1.0.14/libs/magical-plugin-activation/assets/js/admin-plugins.js

    r306496 r357072  
    1 /**
    2  * Shop Toolkit Pro Plugin Recommendations Admin JavaScript
    3  */
    4 
    51(function($) {
    62    'use strict';
    7 
    83    $(document).ready(function() {
    9         // Initialize plugin recommendations
    104        PluginRecommendations.init();
    115    });
    12 
    136    var PluginRecommendations = {
    14        
    157        init: function() {
    168            this.bindEvents();
    179            this.initFilters();
    18            
    19             // Check if recommended plugins notice should be hidden
    2010            if (window.location.href.indexOf('wp-admin') !== -1) {
    2111                this.checkRecommendedPluginsStatus();
    2212            }
    2313        },
    24 
    2514        bindEvents: function() {
    26             // Install plugin
    2715            $(document).on('click', '.install-plugin', this.installPlugin);
    28            
    29             // Activate plugin
    3016            $(document).on('click', '.activate-plugin', this.activatePlugin);
    31            
    32             // Update plugin
    3317            $(document).on('click', '.update-plugin', this.updatePlugin);
    34            
    35             // Filter tabs
    3618            $(document).on('click', '.filter-tab', this.filterPlugins);
    37            
    38             // Dismiss install notice - Handle .install-dismiss buttons and #install-dismiss ID
    3919            $(document).on('click', '.install-dismiss, #install-dismiss', this.dismissInstallNotice);
    40            
    41             // Bulk install required plugins
    42             $(document).on('click', '#install-required-plugins', this.bulkInstallRequired);
    43            
    44             // Bulk install recommended plugins
     20            $(document).on('click', '#install-essential-plugins', this.bulkInstallEssential);
    4521            $(document).on('click', '#install-recommended-plugins', this.bulkInstallRecommended);
    46            
    47             // Update all plugins
     22            $(document).on('click', '#install-all-plugins', this.bulkInstallAll);
    4823            $(document).on('click', '#update-all-plugins', this.updateAllPlugins);
    4924        },
    50 
    5125        initFilters: function() {
    52             // Set initial counts
    5326            this.updateFilterCounts();
    5427        },
    55 
    5628        installPlugin: function(e) {
    5729            e.preventDefault();
    58            
    5930            var $button = $(this);
    6031            var slug = $button.data('slug');
    6132            var isLocal = $button.data('is-local') === 1;
    62             var originalText = $button.text();
    63            
    64             // Disable button and show loading
    65             $button.addClass('loading').prop('disabled', true);
    66            
     33            $button.addClass('loading').prop('disabled', true);
    6734            $.ajax({
    6835                url: MagicalPluginActivation.ajaxurl,
    … …  
    7643                success: function(response) {
    7744                    if (response.success) {
    78                         PluginRecommendations.showMessage($button, response.data.message || MagicalPluginActivation.strings.installed, 'success');
    79                        
    80                         // Update plugin status
     45                        PluginRecommendations.showMessage($button, MagicalPluginActivation.strings.installed, 'success');
    8146                        setTimeout(function() {
    8247                            PluginRecommendations.updatePluginStatus(slug, 'inactive');
    83                            
    84                             // Auto-activate the plugin
    8548                            $button.removeClass('loading').trigger('click');
    8649                        }, 1000);
    8750                    } else {
    88                         PluginRecommendations.showMessage($button, response.data.message || MagicalPluginActivation.strings.error, 'error');
     51                        PluginRecommendations.showMessage($button, MagicalPluginActivation.strings.error, 'error');
    8952                        $button.removeClass('loading').prop('disabled', false);
    9053                    }
    … …  
    9659            });
    9760        },
    98 
    9961        activatePlugin: function(e) {
    10062            e.preventDefault();
    101            
    10263            var $button = $(this);
    10364            var file = $button.data('file');
    10465            var slug = $button.data('slug');
    105             var originalText = $button.text();
    106            
    107             // Disable button and show loading
    108             $button.addClass('loading').prop('disabled', true);
    109            
     66            $button.addClass('loading').prop('disabled', true);
    11067            $.ajax({
    11168                url: MagicalPluginActivation.ajaxurl,
    … …  
    11976                    if (response.success) {
    12077                        PluginRecommendations.showMessage($button, MagicalPluginActivation.strings.activated, 'success');
    121                        
    122                         // Update plugin status
    12378                        setTimeout(function() {
    12479                            PluginRecommendations.updatePluginStatus(slug, 'active');
    125                            
    126                             // Check if all recommended plugins are now active
    12780                            PluginRecommendations.checkRecommendedPluginsStatus();
    128                            
    129                             // Reload page after activation to refresh plugin status
    130                             setTimeout(function() {
    131                                 location.reload();
    132                             }, 2000);
     81                            setTimeout(function() { location.reload(); }, 2000);
    13382                        }, 1000);
    13483                    } else {
    135                         PluginRecommendations.showMessage($button, response.data || MagicalPluginActivation.strings.error, 'error');
     84                        PluginRecommendations.showMessage($button, MagicalPluginActivation.strings.error, 'error');
    13685                        $button.removeClass('loading').prop('disabled', false);
    13786                    }
    … …  
    14392            });
    14493        },
    145 
    14694        updatePlugin: function(e) {
    14795            e.preventDefault();
    148            
    14996            var $button = $(this);
    15097            var slug = $button.data('slug');
    15198            var file = $button.data('file');
    15299            var isLocal = $button.data('is-local') === 1;
    153             var originalText = $button.text();
    154            
    155             // Disable button and show loading
    156             $button.addClass('loading').prop('disabled', true);
    157            
     100            $button.addClass('loading').prop('disabled', true);
    158101            $.ajax({
    159102                url: MagicalPluginActivation.ajaxurl,
    … …  
    168111                success: function(response) {
    169112                    if (response.success) {
    170                         PluginRecommendations.showMessage($button, response.data.message || MagicalPluginActivation.strings.updated, 'success');
    171                        
    172                         // Update plugin status to active (since it was reactivated)
     113                        PluginRecommendations.showMessage($button, MagicalPluginActivation.strings.updated, 'success');
    173114                        setTimeout(function() {
    174115                            PluginRecommendations.updatePluginStatus(slug, 'active');
    175                            
    176                             // Check if all recommended plugins are now active
    177116                            PluginRecommendations.checkRecommendedPluginsStatus();
    178117                        }, 1000);
    179118                    } else {
    180                         PluginRecommendations.showMessage($button, response.data.message || MagicalPluginActivation.strings.error, 'error');
     119                        PluginRecommendations.showMessage($button, MagicalPluginActivation.strings.error, 'error');
    181120                        $button.removeClass('loading').prop('disabled', false);
    182121                    }
    … …  
    188127            });
    189128        },
    190 
    191129        filterPlugins: function(e) {
    192130            e.preventDefault();
    193            
    194131            var $tab = $(this);
    195132            var filter = $tab.data('filter');
    196            
    197             // Update active tab
    198133            $('.filter-tab').removeClass('active');
    199134            $tab.addClass('active');
    200            
    201             // Filter plugin cards
    202135            $('.plugin-card').each(function() {
    203136                var $card = $(this);
    204137                var status = $card.data('status');
    205138                var featured = $card.data('featured');
    206                 var required = $card.data('required');
     139                var essential = $card.data('essential');
    207140                var show = false;
    208                
    209141                switch (filter) {
    210                     case 'all':
    211                         show = true;
    212                         break;
    213                     case 'featured':
    214                         show = featured == 1;
    215                         break;
    216                     case 'required':
    217                         show = required == 1;
    218                         break;
    219                     case 'active':
    220                         show = status === 'active';
    221                         break;
    222                     case 'inactive':
    223                         show = status === 'inactive';
    224                         break;
    225                     case 'not-installed':
    226                         show = status === 'not-installed';
    227                         break;
    228                 }
    229                
    230                 if (show) {
    231                     $card.removeClass('hidden').fadeIn(300);
    232                 } else {
    233                     $card.addClass('hidden').fadeOut(300);
    234                 }
    235             });
    236            
    237             // Update URL without reloading
     142                    case 'all': show = true; break;
     143                    case 'featured': show = featured == 1; break;
     144                    case 'essential': show = essential == 1; break;
     145                    case 'active': show = status === 'active'; break;
     146                    case 'inactive': show = status === 'inactive'; break;
     147                    case 'not-installed': show = status === 'not-installed'; break;
     148                }
     149                if (show) { $card.removeClass('hidden').fadeIn(300); }
     150                else { $card.addClass('hidden').fadeOut(300); }
     151            });
    238152            if (history.pushState) {
    239153                var newUrl = window.location.href.split('?')[0] + '?page=magical-plugin-activation-plugins';
    240                 if (filter !== 'all') {
    241                     newUrl += '&filter=' + filter;
    242                 }
     154                if (filter !== 'all') { newUrl += '&filter=' + filter; }
    243155                history.pushState(null, null, newUrl);
    244156            }
    245157        },
    246 
    247158        updateFilterCounts: function() {
    248             var counts = {
    249                 all: 0,
    250                 featured: 0,
    251                 required: 0,
    252                 active: 0,
    253                 inactive: 0,
    254                 'not-installed': 0
    255             };
    256            
     159            var counts = { all: 0, featured: 0, essential: 0, active: 0, inactive: 0, 'not-installed': 0 };
    257160            $('.plugin-card').each(function() {
    258161                var $card = $(this);
    259162                var status = $card.data('status');
    260163                var featured = $card.data('featured');
    261                 var required = $card.data('required');
    262                
     164                var essential = $card.data('essential');
    263165                counts.all++;
    264166                counts[status]++;
    265                
    266                 if (featured == 1) {
    267                     counts.featured++;
    268                 }
    269                
    270                 if (required == 1) {
    271                     counts.required++;
    272                 }
    273             });
    274            
    275             // Update tab text with counts
     167                if (featured == 1) counts.featured++;
     168                if (essential == 1) counts.essential++;
     169            });
    276170            $('.filter-tab').each(function() {
    277171                var $tab = $(this);
    … …  
    279173                var count = counts[filter];
    280174                var baseText = $tab.text().split(' (')[0];
    281                
    282                 if (count > 0) {
    283                     $tab.text(baseText + ' (' + count + ')');
    284                 } else {
    285                     $tab.text(baseText);
    286                 }
    287             });
    288         },
    289 
     175                if (count > 0) { $tab.text(baseText + ' (' + count + ')'); }
     176                else { $tab.text(baseText); }
     177            });
     178        },
    290179        showMessage: function($button, message, type) {
    291180            var $card = $button.closest('.plugin-card');
    … …  
    294183                .addClass(type === 'error' ? 'error' : '')
    295184                .appendTo($card);
    296            
    297             // Show message
    298             setTimeout(function() {
    299                 $message.addClass('show');
    300             }, 100);
    301            
    302             // Hide message after 3 seconds
     185            setTimeout(function() { $message.addClass('show'); }, 100);
    303186            setTimeout(function() {
    304187                $message.removeClass('show');
    305                 setTimeout(function() {
    306                     $message.remove();
    307                 }, 300);
     188                setTimeout(function() { $message.remove(); }, 300);
    308189            }, 3000);
    309190        },
    310 
    311         // NEW: dismissInstallNotice function to handle .install-dismiss button clicks
     191        updatePluginStatus: function(slug, status) {
     192            var $card = $('.plugin-card[data-slug="' + slug + '"]');
     193            if (!$card.length) return;
     194            $card.attr('data-status', status)
     195                .removeClass('status-active status-inactive status-not-installed')
     196                .addClass('status-' + status);
     197            $card.find('.plugin-status').text(status.charAt(0).toUpperCase() + status.slice(1).replace('-', ' '));
     198            this.updateFilterCounts();
     199        },
    312200        dismissInstallNotice: function(e) {
    313201            e.preventDefault();
    314202            var $button = $(this);
    315203            var $notice = $button.closest('.notice');
    316             // Determine notice type based on CSS class
    317             var noticeType = 'recommended'; // default
    318             if ($notice.hasClass('magical-plugin-activation-pro-recommended-notice')) {
    319                 noticeType = 'recommended';
    320             } else if ($notice.hasClass('magical-plugin-activation-pro-update-notice')) {
    321                 noticeType = 'update';
    322             } else if ($notice.hasClass('magical-plugin-activation-pro-required-notice')) {
    323                 noticeType = 'install'; // Use 'install' for required plugins notice
    324             }
    325 
    326             // Two-step dismiss for required plugins
     204            var noticeType = 'recommended';
     205            if ($notice.hasClass('magical-plugin-activation-pro-recommended-notice')) { noticeType = 'recommended'; }
     206            else if ($notice.hasClass('magical-plugin-activation-pro-update-notice')) { noticeType = 'update'; }
     207            else if ($notice.hasClass('magical-plugin-activation-pro-essential-notice')) { noticeType = 'install'; }
    327208            if (noticeType === 'install') {
    328209                if (!$button.data('confirm-dismiss')) {
    329                     // First click: show warning, do not dismiss
    330                     // Remove any previous warning
    331                     $notice.find('.magical-plugin-activation-required-warning').remove();
    332                     // Add warning message
    333                     var warning = $('<div class="magical-plugin-activation-required-warning" style="color:#b71c1c; margin-top:8px; font-weight:bold;">'+
    334                         (MagicalPluginActivation && MagicalPluginActivation.strings && MagicalPluginActivation.strings.requiredWarning ? MagicalPluginActivation.strings.requiredWarning :
    335                         'You must install and activate all required plugins before dismissing this notice. Click Dismiss again to hide this warning.')+
    336                         '</div>');
     210                    $notice.find('.magical-plugin-activation-essential-warning').remove();
     211                    var warning = $('<div class="magical-plugin-activation-essential-warning" style="color:#b71c1c; margin-top:8px; font-weight:bold;">'+MagicalPluginActivation.strings.essentialWarning+'</div>');
    337212                    $notice.find('p').append(warning);
    338213                    $button.data('confirm-dismiss', true);
    339214                    return;
    340215                }
    341                 // Second click: proceed with AJAX and dismiss
    342216            }
    343 
    344             // Send AJAX request to hide notice permanently
    345217            var requestData = {
    346218                action: 'magical_plugin_activation_dismiss_plugin_notice',
    347219                nonce: MagicalPluginActivation.nonce
    348220            };
    349             // Add notice_type or use specific action for different notices
    350             if (noticeType === 'update') {
    351                 requestData.action = 'magical_plugin_activation_dismiss_update_notice';
    352             } else if (noticeType === 'install') {
    353                 requestData.action = 'magical_plugin_activation_dismiss_install_notice';
    354             } else {
    355                 requestData.notice_type = noticeType;
    356             }
     221            if (noticeType === 'update') { requestData.action = 'magical_plugin_activation_dismiss_update_notice'; }
     222            else if (noticeType === 'install') { requestData.action = 'magical_plugin_activation_dismiss_install_notice'; }
     223            else { requestData.notice_type = noticeType; }
    357224            $.post(MagicalPluginActivation.ajaxurl, requestData);
    358             // Hide the notice with animation
    359             $notice.fadeOut(300, function() {
    360                 $(this).remove();
    361             });
    362         },
    363 
    364         bulkInstallRequired: function(e) {
    365             e.preventDefault();
    366            
    367             var $button = $(this);
    368             var originalText = $button.text();
    369            
    370             // Disable button and show loading
    371             $button.addClass('loading').prop('disabled', true);
    372            
    373             // Add progress indicator
    374             var $progress = $('<div class="bulk-install-progress active"><div class="progress-bar"><div class="progress-fill"></div></div><div class="progress-text">Preparing to install required plugins...</div></div>');
     225            $notice.fadeOut(300, function() { $(this).remove(); });
     226        },
     227        bulkInstallEssential: function(e) {
     228            e.preventDefault();
     229            var $button = $(this);
     230            $button.addClass('loading').prop('disabled', true);
     231            var $progress = $('<div class="bulk-install-progress active"><div class="progress-bar"><div class="progress-fill"></div></div><div class="progress-text">Preparing to install essential plugins...</div></div>');
    375232            $button.after($progress);
    376            
    377             // Animate progress bar from 0% to 30% while waiting for response
    378233            setTimeout(function() {
    379234                $progress.find('.progress-fill').css('width', '30%');
    380                 $progress.find('.progress-text').text('Installing required plugins...');
     235                $progress.find('.progress-text').text('Installing essential plugins...');
    381236            }, 200);
    382            
    383             // Simulate additional progress steps
    384237            setTimeout(function() {
    385238                if ($progress.find('.progress-fill').css('width') === '30%') {
    … …  
    388241                }
    389242            }, 2000);
    390            
    391243            setTimeout(function() {
    392244                if ($progress.find('.progress-fill').css('width') === '60%') {
    … …  
    395247                }
    396248            }, 4000);
    397            
    398             $.ajax({
    399                 url: MagicalPluginActivation.ajaxurl,
    400                 type: 'POST',
    401                 data: {
    402                     action: 'magical_plugin_activation_install_required_plugins',
    403                     nonce: MagicalPluginActivation.nonce
    404                 },
    405                 success: function(response) {
    406                     $button.removeClass('loading').prop('disabled', false);
    407                    
    408                     if (response.success) {
    409                         // Animate progress to 100%
     249            $.ajax({
     250                url: MagicalPluginActivation.ajaxurl,
     251                type: 'POST',
     252                data: {
     253                    action: 'magical_plugin_activation_install_essential_plugins',
     254                    nonce: MagicalPluginActivation.nonce
     255                },
     256                success: function(response) {
     257                    $button.removeClass('loading').prop('disabled', false);
     258                    if (response.success) {
    410259                        $progress.find('.progress-fill').css('width', '100%');
    411                         $progress.find('.progress-text').text('All required plugins installed and activated!');
    412                        
    413                         // Show success message
    414                         var $notice = $('<div class="notice notice-success is-dismissible"><p>' + response.data.message + '</p></div>');
    415                         $('.magical-plugin-activation-plugins h1').after($notice);
    416                        
    417                         // Hide progress after 2 seconds
    418                         setTimeout(function() {
    419                             $progress.fadeOut(300, function() {
    420                                 $(this).remove();
    421                             });
    422                         }, 2000);
    423                        
    424                         // Hide the install button and warning notice
     260                        $progress.find('.progress-text').text('All essential plugins installed and activated!');
     261                        setTimeout(function() { $progress.fadeOut(300, function() { $(this).remove(); }); }, 2000);
    425262                        $button.closest('.notice').fadeOut(300);
    426                        
    427                         // Refresh the page after 3 seconds to update plugin status
    428                         setTimeout(function() {
    429                             location.reload();
    430                         }, 3000);
    431                        
     263                        setTimeout(function() { location.reload(); }, 3000);
    432264                    } else {
    433                         // Show error message
    434                         var $notice = $('<div class="notice notice-error is-dismissible"><p>' + response.data.message + '</p></div>');
    435                         $('.magical-plugin-activation-plugins h1').after($notice);
    436                        
    437265                        $progress.remove();
    438266                    }
    … …  
    440268                error: function() {
    441269                    $button.removeClass('loading').prop('disabled', false);
    442                    
    443                     // Show error message
    444                     var $notice = $('<div class="notice notice-error is-dismissible"><p>An error occurred while installing plugins. Please try again.</p></div>');
    445                     $('.magical-plugin-activation-plugins h1').after($notice);
    446                    
    447270                    $progress.remove();
    448271                }
    449272            });
    450273        },
    451 
    452274        bulkInstallRecommended: function(e) {
    453275            e.preventDefault();
    454            
    455             var $button = $(this);
    456             var originalText = $button.text();
    457            
    458             // Disable button and show loading
    459             $button.addClass('loading').prop('disabled', true);
    460            
    461             // Add progress indicator
     276            var $button = $(this);
     277            $button.addClass('loading').prop('disabled', true);
    462278            var $progress = $('<div class="bulk-install-progress active"><div class="progress-bar"><div class="progress-fill"></div></div><div class="progress-text">Preparing to install recommended plugins...</div></div>');
    463279            $button.after($progress);
    464            
    465             // Animate progress bar from 0% to 30% while waiting for response
    466280            setTimeout(function() {
    467281                $progress.find('.progress-fill').css('width', '30%');
    468282                $progress.find('.progress-text').text('Installing recommended plugins...');
    469283            }, 200);
    470            
    471             // Simulate additional progress steps
    472284            setTimeout(function() {
    473285                if ($progress.find('.progress-fill').css('width') === '30%') {
    … …  
    476288                }
    477289            }, 2000);
    478            
    479290            setTimeout(function() {
    480291                if ($progress.find('.progress-fill').css('width') === '60%') {
    … …  
    483294                }
    484295            }, 4000);
    485            
    486296            $.ajax({
    487297                url: MagicalPluginActivation.ajaxurl,
    … …  
    493303                success: function(response) {
    494304                    $button.removeClass('loading').prop('disabled', false);
    495                    
    496                     if (response.success) {
    497                         // Animate progress to 100%
     305                    if (response.success) {
    498306                        $progress.find('.progress-fill').css('width', '100%');
    499307                        $progress.find('.progress-text').text('All recommended plugins installed and activated!');
    500                        
    501                         // Show success message
    502                         var $notice = $('<div class="notice notice-success is-dismissible"><p>' + response.data.message + '</p></div>');
    503                         $('h1').first().after($notice);
    504                        
    505                         // Hide progress after 2 seconds
    506                         setTimeout(function() {
    507                             $progress.fadeOut(300, function() {
    508                                 $(this).remove();
    509                             });
    510                         }, 2000);
    511                        
    512                         // Hide the recommended notice immediately
    513                         $button.closest('.notice').fadeOut(300, function() {
    514                             $(this).remove();
    515                         });
    516                        
    517                         // Refresh the page after 3 seconds to update plugin status
    518                         setTimeout(function() {
    519                             location.reload();
    520                         }, 3000);
    521                        
    522                     } else {
    523                         // Show error message
    524                         var $notice = $('<div class="notice notice-error is-dismissible"><p>' + response.data.message + '</p></div>');
    525                         $('h1').first().after($notice);
    526                        
    527                         $progress.remove();
    528                     }
    529                 },
    530                 error: function() {
    531                     $button.removeClass('loading').prop('disabled', false);
    532                    
    533                     // Show error message
    534                     var $notice = $('<div class="notice notice-error is-dismissible"><p>An error occurred while installing plugins. Please try again.</p></div>');
    535                     $('h1').first().after($notice);
    536                    
     308                        setTimeout(function() { $progress.fadeOut(300, function() { $(this).remove(); }); }, 2000);
     309                        $button.closest('.notice').fadeOut(300, function() { $(this).remove(); });
     310                        setTimeout(function() { location.reload(); }, 3000);
     311                    } else { $progress.remove(); }
     312                },
     313                error: function() {
     314                    $button.removeClass('loading').prop('disabled', false);
    537315                    $progress.remove();
    538316                }
    539317            });
    540318        },
    541 
     319        bulkInstallAll: function(e) {
     320            e.preventDefault();
     321            var $button = $(this);
     322            $button.addClass('loading').prop('disabled', true);
     323            var $progress = $('<div class="bulk-install-progress active"><div class="progress-bar"><div class="progress-fill"></div></div><div class="progress-text">Preparing to install plugins...</div></div>');
     324            $button.after($progress);
     325            setTimeout(function() {
     326                $progress.find('.progress-fill').css('width', '30%');
     327                $progress.find('.progress-text').text('Installing plugins...');
     328            }, 200);
     329            setTimeout(function() {
     330                if ($progress.find('.progress-fill').css('width') === '30%') {
     331                    $progress.find('.progress-fill').css('width', '60%');
     332                    $progress.find('.progress-text').text('Activating plugins...');
     333                }
     334            }, 2000);
     335            setTimeout(function() {
     336                if ($progress.find('.progress-fill').css('width') === '60%') {
     337                    $progress.find('.progress-fill').css('width', '80%');
     338                    $progress.find('.progress-text').text('Finalizing installation...');
     339                }
     340            }, 4000);
     341            $.ajax({
     342                url: MagicalPluginActivation.ajaxurl,
     343                type: 'POST',
     344                data: {
     345                    action: 'magical_plugin_activation_install_all_plugins',
     346                    nonce: MagicalPluginActivation.nonce
     347                },
     348                success: function(response) {
     349                    $button.removeClass('loading').prop('disabled', false);
     350                    if (response.success) {
     351                        $progress.find('.progress-fill').css('width', '100%');
     352                        $progress.find('.progress-text').text('All plugins installed and activated!');
     353                        setTimeout(function() { $progress.fadeOut(300, function() { $(this).remove(); }); }, 2000);
     354                        $button.closest('.notice').fadeOut(300, function() { $(this).remove(); });
     355                        setTimeout(function() { location.reload(); }, 3000);
     356                    } else { $progress.remove(); }
     357                },
     358                error: function() {
     359                    $button.removeClass('loading').prop('disabled', false);
     360                    $progress.remove();
     361                }
     362            });
     363        },
    542364        updateAllPlugins: function(e) {
    543365            e.preventDefault();
    544            
    545             var $button = $(this);
    546             var originalText = $button.text();
    547            
    548             // Disable button and show loading
     366            var $button = $(this);
    549367            $button.addClass('loading').prop('disabled', true).text(MagicalPluginActivation.strings.updating);
    550            
    551             // Show progress bar
    552             PluginRecommendations.showBulkProgress($button, 'Updating plugins...');
    553            
    554             // Get all plugins that need updates
    555368            var $updateButtons = $('.update-plugin');
    556369            var total = $updateButtons.length;
    557370            var completed = 0;
    558            
    559371            if (total === 0) {
    560                 PluginRecommendations.showMessage($button, 'No plugins need updates', 'info');
    561                 $button.removeClass('loading').prop('disabled', false).text(originalText);
     372                $button.removeClass('loading').prop('disabled', false);
    562373                return;
    563374            }
    564            
    565             // Update each plugin
    566375            $updateButtons.each(function() {
    567376                var $updateBtn = $(this);
    … …  
    569378                var file = $updateBtn.data('file');
    570379                var isLocal = $updateBtn.data('is-local');
    571                
    572380                $.ajax({
    573381                    url: MagicalPluginActivation.ajaxurl,
    … …  
    582390                    success: function(response) {
    583391                        completed++;
    584                        
    585                         if (response.success) {
    586                             PluginRecommendations.updatePluginStatus(slug, 'active');
    587                         }
    588                        
    589                         // Update progress
    590                         var progress = Math.round((completed / total) * 100);
    591                         PluginRecommendations.updateBulkProgress(progress);
    592                        
    593                         // Check if all updates are complete
     392                        if (response.success) { PluginRecommendations.updatePluginStatus(slug, 'active'); }
    594393                        if (completed === total) {
    595394                            setTimeout(function() {
    596                                 PluginRecommendations.hideBulkProgress();
    597                                 PluginRecommendations.showMessage($button, 'All plugins updated successfully!', 'success');
    598                                 $button.removeClass('loading').prop('disabled', false).text(originalText);
    599                                
    600                                 // Hide update notices
    601                                 $('.magical-plugin-activation-pro-update-notice').fadeOut(300, function() {
    602                                     $(this).remove();
    603                                 });
    604                                
    605                                 // Refresh page to update plugin status
    606                                 setTimeout(function() {
    607                                     window.location.reload();
    608                                 }, 1500);
     395                                $button.removeClass('loading').prop('disabled', false);
     396                                $('.magical-plugin-activation-pro-update-notice').fadeOut(300, function() { $(this).remove(); });
     397                                setTimeout(function() { window.location.reload(); }, 1500);
    609398                            }, 500);
    610399                        }
    … …  
    612401                    error: function() {
    613402                        completed++;
    614                        
    615                         // Update progress
    616                         var progress = Math.round((completed / total) * 100);
    617                         PluginRecommendations.updateBulkProgress(progress);
    618                        
    619                         // Check if all updates are complete
    620403                        if (completed === total) {
    621                             setTimeout(function() {
    622                                 PluginRecommendations.hideBulkProgress();
    623                                 PluginRecommendations.showMessage($button, 'Some plugins failed to update', 'error');
    624                                 $button.removeClass('loading').prop('disabled', false).text(originalText);
    625                             }, 500);
     404                            setTimeout(function() { $button.removeClass('loading').prop('disabled', false); }, 500);
    626405                        }
    627406                    }
    … …  
    629408            });
    630409        },
    631 
    632410        checkRecommendedPluginsStatus: function() {
    633             // Check via AJAX if all recommended plugins are active
    634411            $.ajax({
    635412                url: MagicalPluginActivation.ajaxurl,
    … …  
    641418                success: function(response) {
    642419                    if (response.success && response.data.all_active) {
    643                         // Hide recommended notice if all plugins are active
    644                         $('.magical-plugin-activation-pro-plugin-notice').fadeOut(300, function() {
    645                             $(this).remove();
    646                         });
    647                     }
    648                 },
    649                 error: function() {
    650                     // Fallback: check individual plugin cards if available
    651                     var allActive = true;
    652                     $('.plugin-card[data-featured="1"]').each(function() {
    653                         if ($(this).attr('data-status') !== 'active') {
    654                             allActive = false;
    655                             return false; // break
    656                         }
    657                     });
    658                    
    659                     if (allActive) {
    660                         $('.magical-plugin-activation-pro-plugin-notice').fadeOut(300, function() {
    661                             $(this).remove();
    662                         });
     420                        $('.magical-plugin-activation-pro-plugin-notice').fadeOut(300, function() { $(this).remove(); });
    663421                    }
    664422                }
    … …  
    666424        }
    667425    };
    668 
    669     // Expose to global scope for debugging
    670426    window.PluginRecommendations = PluginRecommendations;
    671 
    672427})(jQuery);
  • portfoliox-dark/1.0.14/libs/magical-plugin-activation/class-magical-plugin-activation.php

    r341891 r357072  
    127127        add_action('wp_ajax_magical_plugin_activation_dismiss_install_notice', array($this, 'ajax_dismiss_install_notice'));
    128128        add_action('wp_ajax_magical_plugin_activation_update_all_plugins', array($this, 'ajax_update_all_plugins'));
    129         add_action('wp_ajax_magical_plugin_activation_install_required_plugins', array($this, 'ajax_install_required_plugins'));
     129        add_action('wp_ajax_magical_plugin_activation_install_essential_plugins', array($this, 'ajax_install_essential_plugins'));
    130130        add_action('wp_ajax_magical_plugin_activation_install_recommended_plugins', array($this, 'ajax_install_recommended_plugins'));
     131        add_action('wp_ajax_magical_plugin_activation_install_all_plugins', array($this, 'ajax_install_all_plugins'));
    131132        add_action('wp_ajax_magical_plugin_activation_check_recommended_plugins_status', array($this, 'ajax_check_recommended_plugins_status'));
    132133        add_action('admin_notices', array($this, 'show_recommendation_notice'));
    133134        add_action('admin_notices', array($this, 'show_update_notice'));
    134135       
    135         // Auto-install required plugins
    136         add_action('after_switch_theme', array($this, 'auto_install_required_plugins'));
    137         add_action('admin_init', array($this, 'check_required_plugins'));
    138 
    139         // Timed auto-activation for select plugins (fires once 20h after install)
     136        // Auto-install essential plugins
     137        add_action('after_switch_theme', array($this, 'auto_install_essential_plugins'));
    140138        add_action('after_switch_theme', array($this, 'store_theme_install_time'));
     139        add_action('upgrader_process_complete', array($this, 'auto_install_on_theme_update'), 10, 2);
     140        add_action('admin_init', array($this, 'check_essential_plugins'));
    141141        add_action('admin_init', array($this, 'check_timed_auto_plugins'));
    142142    }
    … …  
    176176                'description' => __('Easily add social sharing buttons to your content.', 'portfoliox-dark'),
    177177                'category' => 'Utility',
    178                 'required' => false,
    179                 'featured' => true,
    180                 'is_local' => false
    181             ),
    182             'magical-blocks' => array(
    183                 'name' => __('Magical Blocks', 'portfoliox-dark'),
    184                 'slug' => 'magical-blocks',
    185                 'file' => 'magical-blocks/magical-blocks.php',
    186                 'description' => __('Magical Blocks WordPress theme for update WordPress editor', 'portfoliox-dark'),
    187                 'category' => 'Utility',
    188                 'required' => true,
     178                'essential' => false,
    189179                'featured' => true,
    190180                'is_local' => false
    … …  
    198188                'description' => __('Easily manage password protection for your WordPress content.', 'portfoliox-dark'),
    199189                'category' => 'Security',
    200                 'required' => true,
     190                'essential' => false,
    201191                'featured' => true,
    202192                'is_local' => false
    203193            ),
    204             // Essential Plugins
    205             'magical-addons-for-elementor' => array(
    206                 'name' => __('Magical Addons', 'portfoliox-dark'),
    207                 'slug' => 'magical-addons-for-elementor',
    208                 'file' => 'magical-addons-for-elementor/magical-addons-for-elementor.php',
    209                 'description' => __('Enhance your site with a collection of magical addons for Elementor.', 'portfoliox-dark'),
    210                 'category' => 'Essential',
    211                 'required' => false,
    212                 'featured' => false,
    213                 'is_local' => false
    214             ),
    215            
    216             'magical-posts-display' => array(
    217                 'name' => __('Magical Posts Display', 'portfoliox-dark'),
    218                 'slug' => 'magical-posts-display',
    219                 'file' => 'magical-posts-display/magical-posts-display.php',
    220                 'description' => __('Display your posts in a magical way with this addon for Elementor.', 'portfoliox-dark'),
    221                 'category' => 'Essential',
    222                 'required' => false,
     194            'ai-marketing-expert' => array(
     195                'name' => __('AI Marketing Expert', 'portfoliox-dark'),
     196                'slug' => 'ai-marketing-expert',
     197                'file' => 'ai-marketing-expert/ai-marketing-expert.php',
     198                'description' => __('AI-powered marketing suite with email marketing, content generator, SEO analyzer, social media, and chatbot.', 'portfoliox-dark'),
     199                'category' => 'Marketing',
     200                'essential' => false,
     201                'timed_auto' => true,
    223202                'featured' => true,
    224                 'is_local' => false
    225             ),
    226            
    227             'magical-blocks' => array(
    228                 'name' => __('Magical Blocks', 'portfoliox-dark'),
    229                 'slug' => 'magical-blocks',
    230                 'file' => 'magical-blocks/magical-blocks.php',
    231                 'description' => __('Add magical blocks to your content.', 'portfoliox-dark'),
    232                 'category' => 'Utility',
    233                 'required' => false,
    234                 'featured' => false,
    235                 'is_local' => false
    236             ),
    237            
    238             // Page Builder
    239             'elementor' => array(
    240                 'name' => __('Elementor Page Builder', 'portfoliox-dark'),
    241                 'slug' => 'elementor',
    242                 'file' => 'elementor/elementor.php',
    243                 'description' => __('Create beautiful pages with drag & drop page builder. Perfect for creating stunning layouts with your theme.', 'portfoliox-dark'),
    244                 'category' => 'Page Builder',
    245                 'required' => false,
    246                 'featured' => true,
    247                 'is_local' => false
    248             ),
    249            
    250             // Utility Plugins
    251             'click-to-top' => array(
    252                 'name' => __('Click to Top', 'portfoliox-dark'),
    253                 'slug' => 'click-to-top',
    254                 'file' => 'click-to-top/click-to-top.php',
    255                 'description' => __('Add a "click to top" button to your site for better user experience.', 'portfoliox-dark'),
    256                 'category' => 'Utility',
    257                 'required' => false,
    258                 'featured' => false,
    259203                'is_local' => false
    260204            ),
    … …  
    370314            <?php
    371315            // Check if there are missing required plugins
    372             $missing_required = array();
    373             $required_plugins = $this->get_required_plugins();
    374            
    375             foreach ($required_plugins as $slug => $plugin) {
     316            $missing_essential = array();
     317            $essential_plugins = $this->get_essential_plugins();
     318           
     319            foreach ($essential_plugins as $slug => $plugin) {
    376320                if ($this->get_plugin_status($plugin) !== 'active') {
    377                     $missing_required[$slug] = $plugin;
    378                 }
    379             }
    380            
    381             if (!empty($missing_required)) :
     321                    $missing_essential[$slug] = $plugin;
     322                }
     323            }
     324           
     325            if (!empty($missing_essential)) :
    382326            ?>
    383327            <div class="notice notice-warning">
    384328                <p>
    385                     <strong><?php esc_html_e('Missing Required Plugins:', 'portfoliox-dark'); ?></strong>
    386                     <?php printf(esc_html__('%d required plugins are missing or inactive.', 'portfoliox-dark'), count($missing_required)); ?>
    387                     <button id="install-required-plugins" class="button button-primary" style="margin-left: 10px;">
    388                         <?php esc_html_e('Install Required Plugins', 'portfoliox-dark'); ?>
     329                    <strong><?php esc_html_e('Missing Essential Plugins:', 'portfoliox-dark'); ?></strong>
     330                    <?php printf(esc_html__('%d essential plugins are missing or inactive.', 'portfoliox-dark'), count($missing_essential)); ?>
     331                    <button id="install-essential-plugins" class="button button-primary" style="margin-left: 10px;">
     332                        <?php esc_html_e('Install Essential Plugins', 'portfoliox-dark'); ?>
    389333                    </button>
    390334                </p>
    … …  
    397341                'all' => count($plugins),
    398342                'featured' => 0,
    399                 'required' => 0,
     343                'essential' => 0,
    400344                'active' => 0,
    401345                'inactive' => 0,
    … …  
    406350                $status = $this->get_plugin_status($plugin);
    407351               
    408                 if ($plugin['featured']) {
     352                if (!empty($plugin['featured'])) {
    409353                    $plugin_counts['featured']++;
    410354                }
    411355               
    412                 if ($plugin['required']) {
    413                     $plugin_counts['required']++;
     356                if (!empty($plugin['essential'])) {
     357                    $plugin_counts['essential']++;
    414358                }
    415359               
    … …  
    440384                if (empty($first_active_tab)) $first_active_tab = 'featured';
    441385            }
    442             if ($plugin_counts['required'] > 0) {
    443                 $available_tabs[] = 'required';
    444                 if (empty($first_active_tab)) $first_active_tab = 'required';
     386            if ($plugin_counts['essential'] > 0) {
     387                $available_tabs[] = 'essential';
     388                if (empty($first_active_tab)) $first_active_tab = 'essential';
    445389            }
    446390            if ($plugin_counts['active'] > 0) {
    … …  
    467411                <?php endif; ?>
    468412               
    469                 <?php if ($plugin_counts['required'] > 0) : ?>
    470                     <button class="filter-tab <?php echo ($first_active_tab === 'required') ? 'active' : ''; ?>" data-filter="required"><?php printf(esc_html__('Required (%d)', 'portfoliox-dark'), $plugin_counts['required']); ?></button>
     413                <?php if ($plugin_counts['essential'] > 0) : ?>
     414                    <button class="filter-tab <?php echo ($first_active_tab === 'essential') ? 'active' : ''; ?>" data-filter="essential"><?php printf(esc_html__('Essential (%d)', 'portfoliox-dark'), $plugin_counts['essential']); ?></button>
    471415                <?php endif; ?>
    472416               
    … …  
    491435                    $is_local = $this->is_local_plugin($plugin);
    492436                ?>
    493                     <div class="plugin-card <?php echo esc_attr($featured_class); ?>" data-status="<?php echo esc_attr($status); ?>" data-featured="<?php echo $plugin['featured'] ? '1' : '0'; ?>" data-required="<?php echo $plugin['required'] ? '1' : '0'; ?>" data-local="<?php echo $is_local ? '1' : '0'; ?>" data-slug="<?php echo esc_attr($slug); ?>">
     437                    <div class="plugin-card <?php echo esc_attr($featured_class); ?>" data-status="<?php echo esc_attr($status); ?>" data-featured="<?php echo !empty($plugin['featured']) ? '1' : '0'; ?>" data-essential="<?php echo !empty($plugin['essential']) ? '1' : '0'; ?>" data-local="<?php echo $is_local ? '1' : '0'; ?>" data-slug="<?php echo esc_attr($slug); ?>">
    494438                        <?php if ($plugin['featured']) : ?>
    495439                            <div class="featured-badge"><?php esc_html_e('Featured', 'portfoliox-dark'); ?></div>
    496440                        <?php endif; ?>
    497441                       
    498                         <?php if ($plugin['required']) : ?>
    499                             <div class="required-badge"><?php esc_html_e('Required', 'portfoliox-dark'); ?></div>
     442                        <?php if (!empty($plugin['essential'])) : ?>
     443                            <div class="essential-badge"><?php esc_html_e('Essential', 'portfoliox-dark'); ?></div>
    500444                        <?php endif; ?>
    501445                       
    … …  
    633577                    </div>
    634578                </div>
    635                 <div class="plugin-icon-recomend">🔄</div>
    636579            </div>
    637580        </div>
    … …  
    775718                'update' => __('Update', 'portfoliox-dark'),
    776719                'error' => __('Error occurred', 'portfoliox-dark'),
    777                 'requiredWarning' => __('You must install and activate all required plugins before dismissing this notice. Click Dismiss again to hide this warning.', 'portfoliox-dark'),
     720                'essentialWarning' => __('You must install and activate all essential plugins before dismissing this notice. Click Dismiss again to hide this warning.', 'portfoliox-dark'),
    778721            )
    779722        ));
    … …  
    932875     * AJAX handler for bulk installing required plugins
    933876     */
    934     public function ajax_install_required_plugins() {
     877    public function ajax_install_essential_plugins() {
    935878        check_ajax_referer('magical_plugin_activation_plugins_nonce', 'nonce');
    936879       
    … …  
    939882        }
    940883       
    941         $required_plugins = $this->get_required_plugins();
     884        $essential_plugins = $this->get_essential_plugins();
    942885        $results = array();
    943886        $success_count = 0;
    944         $total_count = count($required_plugins);
    945        
    946         foreach ($required_plugins as $slug => $plugin) {
     887        $total_count = count($essential_plugins);
     888       
     889        foreach ($essential_plugins as $slug => $plugin) {
    947890            $status = $this->get_plugin_status($plugin);
    948891           
    … …  
    964907        if ($success_count === $total_count) {
    965908            wp_send_json_success(array(
    966                 'message' => sprintf(__('%d required plugins installed and activated successfully.', 'portfoliox-dark'), $success_count),
     909                'message' => sprintf(__('%d essential plugins installed and activated successfully.', 'portfoliox-dark'), $success_count),
    967910                'results' => $results
    968911            ));
    969912        } else {
    970913            wp_send_json_error(array(
    971                 'message' => sprintf(__('%d of %d required plugins installed successfully.', 'portfoliox-dark'), $success_count, $total_count),
     914                'message' => sprintf(__('%d of %d essential plugins installed successfully.', 'portfoliox-dark'), $success_count, $total_count),
    972915                'results' => $results
    973916            ));
    … …  
    1022965   
    1023966    /**
     967     * AJAX handler for bulk installing all plugins (required + recommended)
     968     */
     969    public function ajax_install_all_plugins() {
     970        check_ajax_referer('magical_plugin_activation_plugins_nonce', 'nonce');
     971       
     972        if (!current_user_can('install_plugins')) {
     973            wp_die(__('You do not have permission to install plugins.', 'portfoliox-dark'));
     974        }
     975       
     976        $all_plugins = $this->get_recommended_plugins();
     977        $results = array();
     978        $success_count = 0;
     979        $total_count = count($all_plugins);
     980       
     981        foreach ($all_plugins as $slug => $plugin) {
     982            $status = $this->get_plugin_status($plugin);
     983           
     984            if ($status === 'active') {
     985                $results[$slug] = 'already-active';
     986                $success_count++;
     987            } else {
     988                $installed = $this->install_and_activate_plugin($plugin);
     989               
     990                if ($installed) {
     991                    $results[$slug] = 'installed-and-activated';
     992                    $success_count++;
     993                } else {
     994                    $results[$slug] = 'failed';
     995                }
     996            }
     997        }
     998       
     999        if ($success_count === $total_count) {
     1000            wp_send_json_success(array(
     1001                'message' => sprintf(__('%d plugins installed and activated successfully.', 'portfoliox-dark'), $success_count),
     1002                'results' => $results
     1003            ));
     1004        } else {
     1005            wp_send_json_error(array(
     1006                'message' => sprintf(__('%d of %d plugins installed successfully.', 'portfoliox-dark'), $success_count, $total_count),
     1007                'results' => $results
     1008            ));
     1009        }
     1010    }
     1011   
     1012    /**
    10241013     * AJAX handler to check if all recommended plugins are active
    10251014     */
    … …  
    10411030        $screen = get_current_screen();
    10421031       
    1043         // Only show on dashboard, themes, and plugins pages
    10441032        if (!in_array($screen->id, array('dashboard', 'themes', 'plugins', 'appearance_page_magical-plugin-activation-plugins'))) {
    10451033            return;
    10461034        }
    10471035       
    1048         // Check if there are any missing required plugins
    1049         $missing_required = array();
    1050         $required_plugins = $this->get_required_plugins();
    1051        
    1052         foreach ($required_plugins as $slug => $plugin) {
    1053             if ($this->get_plugin_status($plugin) !== 'active') {
    1054                 $missing_required[$slug] = $plugin;
    1055             }
    1056         }
    1057        
    1058         // Show REQUIRED plugins notice only if there are missing plugins and not dismissed
    1059         if (!empty($missing_required)) {
    1060             // Check if user dismissed the required plugins notice
    1061             $dismissed_time = get_user_meta(get_current_user_id(), 'magical_plugin_activation_hide_install_notice_time', true);
    1062             $show_required_notice = !$dismissed_time || (time() - $dismissed_time) >= (7 * 24 * 60 * 60); // 7 days
    1063            
    1064             if ($show_required_notice) {
    1065                 ?>
    1066             <div class="notice notice-warning magical-plugin-activation-pro-required-notice">
    1067                 <p>
    1068                     <strong><?php echo esc_html($this->theme_name); ?></strong> -
    1069                     <?php printf(esc_html__('%d required plugins are missing. Please install them for optimal theme functionality.', 'portfoliox-dark'), count($missing_required)); ?>
    1070                     <br><br>
    1071                     <button id="install-required-plugins" class="button button-primary" style="margin-right: 10px;">
    1072                         <?php esc_html_e('Install Required Plugins', 'portfoliox-dark'); ?>
    1073                     </button>
    1074                     <a href="<?php echo esc_url(admin_url('themes.php?page=magical-plugin-activation-plugins')); ?>" class="button button-secondary">
    1075                         <?php esc_html_e('View All Plugins', 'portfoliox-dark'); ?>
    1076                     </a>
    1077                      <button id="install-dismiss" class="button install-dismiss" style="margin-left: 10px;">
    1078                         <?php esc_html_e('Dismiss', 'portfoliox-dark'); ?>
    1079                     </button>
    1080                    
    1081                 </p>
    1082             </div>
    1083             <?php
    1084             }
    1085         }
    1086        
    1087         // Show recommended plugins notice (dismissible) only on dashboard and themes pages
    10881036        if (in_array($screen->id, array('dashboard', 'themes', 'plugins'))) {
    10891037            $this->show_recommended_plugins_notice();
    … …  
    11031051        }
    11041052       
    1105         // Check if all recommended plugins are active
     1053        // Check if all plugins are active
    11061054        if ($this->are_all_recommended_plugins_active()) {
    11071055            return;
    11081056        }
    11091057       
    1110         // Get recommended plugins that are not active
    1111         $recommended_plugins = $this->get_recommended_plugins();
     1058        $all_plugins = $this->get_recommended_plugins();
     1059        $missing_essential = array();
    11121060        $inactive_recommended = array();
    11131061       
    1114         foreach ($recommended_plugins as $slug => $plugin) {
    1115             if (!$plugin['required'] && $this->get_plugin_status($plugin) !== 'active') {
    1116                 $inactive_recommended[$slug] = $plugin;
    1117             }
    1118         }
    1119        
    1120         if (empty($inactive_recommended)) {
    1121             return;
    1122         }
     1062        foreach ($all_plugins as $slug => $plugin) {
     1063            $status = $this->get_plugin_status($plugin);
     1064            if ($status !== 'active') {
     1065                if (!empty($plugin['essential'])) {
     1066                    $missing_essential[$slug] = $plugin;
     1067                } else {
     1068                    $inactive_recommended[$slug] = $plugin;
     1069                }
     1070            }
     1071        }
     1072       
     1073        $has_essential = !empty($missing_essential);
     1074        $total_missing = count($missing_essential) + count($inactive_recommended);
     1075       
     1076        if ($total_missing === 0) {
     1077            return;
     1078        }
     1079       
     1080        $button_id = 'install-all-plugins';
     1081        $button_text = __('Install Plugins', 'portfoliox-dark');
     1082        $heading = __('Plugins for %s', 'portfoliox-dark');
     1083        $description = $has_essential
     1084            ? __('%d plugins are missing or inactive. Install them for optimal theme functionality.', 'portfoliox-dark')
     1085            : __('We recommend %d additional plugins to enhance your %s theme experience.', 'portfoliox-dark');
    11231086       
    11241087        ?>
    … …  
    11261089            <div class="plugin-recommended-content">
    11271090                <div style="flex: 1;">
    1128                     <h3><?php printf(esc_html__('Recommended Plugins for %s', 'portfoliox-dark'), $this->theme_name); ?></h3>
    1129                     <p><?php printf(esc_html__('We recommend %d additional plugins to enhance your %s theme experience.', 'portfoliox-dark'), count($inactive_recommended), $this->theme_name); ?></p>
     1091                    <h3><?php printf(esc_html($heading), $this->theme_name); ?></h3>
     1092                    <p><?php printf(esc_html($description), $total_missing, $this->theme_name); ?></p>
    11301093                    <div style="display: flex; gap: 12px; align-items: center; flex-wrap: wrap; margin-top: 15px;">
    1131                         <button id="install-recommended-plugins" class="button button-primary"><?php esc_html_e('Install Recommended Plugins', 'portfoliox-dark'); ?></button>
     1094                        <button id="<?php echo esc_attr($button_id); ?>" class="button button-primary"><?php echo esc_html($button_text); ?></button>
    11321095                        <a href="<?php echo esc_url(admin_url('themes.php?page=magical-plugin-activation-plugins')); ?>" class="button button-secondary"><?php esc_html_e('View All Plugins', 'portfoliox-dark'); ?></a>
    11331096                        <button class="install-dismiss" class="button" style="margin-left: 10px;">
    … …  
    11361099                    </div>
    11371100                </div>
    1138                 <div class="plugin-icon-recomend">🔌</div>
    11391101            </div>
    11401102        </div>
    … …  
    11431105   
    11441106    /**
    1145      * Auto-install required plugins on theme activation
    1146      */
    1147     public function auto_install_required_plugins() {
     1107     * Auto-install essential plugins on theme activation
     1108     */
     1109    public function auto_install_essential_plugins() {
    11481110        // Check if we have permission to install plugins
    11491111        if (!current_user_can('install_plugins')) {
    … …  
    11511113        }
    11521114       
    1153         // Get all required plugins
    1154         $required_plugins = $this->get_required_plugins();
    1155        
    1156         if (empty($required_plugins)) {
     1115        // Load required admin files for upgrader
     1116        if (!function_exists('request_filesystem_credentials')) {
     1117            require_once ABSPATH . 'wp-admin/includes/file.php';
     1118        }
     1119       
     1120        // Get all essential plugins
     1121        $essential_plugins = $this->get_essential_plugins();
     1122       
     1123        if (empty($essential_plugins)) {
    11571124            return;
    11581125        }
    … …  
    11621129       
    11631130        // Install and activate required plugins
    1164         foreach ($required_plugins as $plugin) {
     1131        foreach ($essential_plugins as $plugin) {
    11651132            $this->install_and_activate_plugin($plugin);
    11661133        }
    … …  
    11711138   
    11721139    /**
     1140     * Auto-install essential plugins after theme update
     1141     */
     1142    public function auto_install_on_theme_update($upgrader, $hook_extra) {
     1143        if (!isset($hook_extra['type']) || $hook_extra['type'] !== 'theme') {
     1144            return;
     1145        }
     1146       
     1147        if (!isset($hook_extra['themes']) || !is_array($hook_extra['themes'])) {
     1148            return;
     1149        }
     1150       
     1151        $current_theme = get_template();
     1152        if (!in_array($current_theme, $hook_extra['themes'])) {
     1153            return;
     1154        }
     1155       
     1156        $this->auto_install_essential_plugins();
     1157    }
     1158   
     1159    /**
    11731160     * Check for required plugins on admin init
    11741161     */
    1175     public function check_required_plugins() {
     1162    public function check_essential_plugins() {
    11761163        // Only check if user can install plugins
    11771164        if (!current_user_can('install_plugins')) {
    … …  
    11881175       
    11891176        // Get required plugins
    1190         $required_plugins = $this->get_required_plugins();
    1191        
    1192         if (empty($required_plugins)) {
     1177        $essential_plugins = $this->get_essential_plugins();
     1178       
     1179        if (empty($essential_plugins)) {
    11931180            return;
    11941181        }
    11951182       
    11961183        // Check each required plugin
    1197         foreach ($required_plugins as $plugin) {
     1184        foreach ($essential_plugins as $plugin) {
    11981185            $status = $this->get_plugin_status($plugin);
    11991186           
    … …  
    12091196     * Get only required plugins
    12101197     */
    1211     private function get_required_plugins() {
     1198    private function get_essential_plugins() {
    12121199        $all_plugins = $this->get_recommended_plugins();
    1213         $required_plugins = array();
     1200        $essential_plugins = array();
    12141201       
    12151202        foreach ($all_plugins as $slug => $plugin) {
    1216             if (isset($plugin['required']) && $plugin['required'] === true) {
    1217                 $required_plugins[$slug] = $plugin;
    1218             }
    1219         }
    1220        
    1221         return $required_plugins;
     1203            if (isset($plugin['essential']) && $plugin['essential'] === true) {
     1204                $essential_plugins[$slug] = $plugin;
     1205            }
     1206        }
     1207       
     1208        return $essential_plugins;
    12221209    }
    12231210   
    … …  
    14651452    /**
    14661453     * Fallback manual extraction when WordPress methods fail
    1467     }
     1454     */
    14681455
    14691456    /**
    … …  
    16451632       
    16461633        // Reset old dismissals for migration
    1647         delete_user_meta(get_current_user_id(), 'magical_plugin_activation_hide_required_plugins_notice');
     1634        delete_user_meta(get_current_user_id(), 'magical_plugin_activation_hide_essential_plugins_notice');
    16481635        delete_user_meta(get_current_user_id(), 'magical_plugin_activation_hide_recommended_plugins_notice');
    16491636        delete_user_meta(get_current_user_id(), 'magical_plugin_activation_hide_update_notice_time');
    … …  
    16951682    /**
    16961683     * Check timed auto plugins on admin_init.
    1697      * Fires ONCE 20 hours after install. Never fires again after that.
    16981684     */
    16991685    public function check_timed_auto_plugins() {
    … …  
    17391725new magical_plugin_activation_Plugin_Recommendations();
    17401726
     1727
  • portfoliox-dark/1.0.14/readme.txt

    r341891 r357072  
    55Requires PHP: 7.4
    66Requires at least: 6.0
    7 Tested up to: 7.0
    8 Stable tag: 1.0.13
     7Tested up to: 7.1
     8Stable tag: 1.0.14
    99License: GNU General Public License v2 or later
    1010License URI: http://opensource.org/licenses/gpl-2.0.php
    … …  
    5959
    6060== Changelog ==
     61= 1.0.14 =
     62* Tested with latest WordPress version.
     63* Minor CSS and template improvements.
     64* Updated recommended plugins.
     65
    6166
    6267
  • portfoliox-dark/1.0.14/style.css

    r341891 r357072  
    44Author: Noor Alam
    55Author URI: https://wpthemespace.com/
    6 Version: 1.0.13
     6Version: 1.0.14
    77Requires at least: 6.0
    8 Tested up to: 7.0
     8Tested up to: 7.1
    99Requires PHP: 7.4
    1010Description: PortfolioX Dark is a creative, minimal, clean design and dark mode WordPress portfolio theme. PortfolioX Dark theme designed with attention to detail, flexibility, and performance. PortfolioX Dark theme suitable for personal, freelance, designer, web designer, developer, service, marketing, startup, portfolio, photography, architect, corporate, event, artist, musician, management, nft, blockchain,vcard, and more. The PortfolioX Dark theme layout looks beautiful at any size, be it a desktop screen, iPhone, iPad, Android Mobile. Plus, the theme includes lots of customization options that allows you to change the visual style of any elements without touching to single line of codes.
    … …  
    2323Nicolas Gallagher and Jonathan Neal https://necolas.github.io/normalize.css/
    2424*/
     25
     26/* ==========================================================================
     27   Header Logo & Navigation Spacing Rule (Collision Prevention)
     28   Ensures at least 30-40px gap between logo and menu so they never touch.
     29   ========================================================================== */
     30@media (min-width: 992px) {
     31  .menubar-content,
     32  .pxm-style1 .navigation .d-flex,
     33  .navigation .d-flex,
     34  .site-header .d-flex,
     35  .header-main-wrapper .d-flex {
     36    gap: 35px;
     37  }
     38
     39  .head-logo-sec,
     40  .pxms1-logo,
     41  .site-branding.brand-logo,
     42  .site-branding.brand-text,
     43  .menubar-content .head-logo-sec,
     44  .header-logo-wrap {
     45    flex-shrink: 0;
     46    margin-right: 30px;
     47  }
     48
     49  .main-navigation,
     50  .pxms1-menu,
     51  .real-estate-pack-container.menu-inner {
     52    min-width: 0;
     53  }
     54}
Note: See TracChangeset for help on using the changeset viewer.