Changeset 3755228
- Timestamp:
- 10/19/2026 04:48:49 PM (3 weeks ago)
- Location:
- vefmusic/trunk
- Files:
-
- 15 edited
-
assets/css/vefm-admin.css (modified) (4 diffs)
-
assets/css/vefm-buttons.css (modified) (3 diffs)
-
assets/css/vefm-frontend.css (modified) (3 diffs)
-
assets/css/vefm-lightbox.css (modified) (2 diffs)
-
includes/class-vefm-admin-help.php (modified) (2 diffs)
-
includes/class-vefm-admin-ui.php (modified) (1 diff)
-
includes/class-vefm-admin.php (modified) (16 diffs)
-
includes/class-vefm-press-kit-admin.php (modified) (2 diffs)
-
includes/core/class-vefm-button-shadow.php (modified) (1 diff)
-
includes/core/class-vefm-button-states.php (modified) (6 diffs)
-
includes/core/class-vefm-renderer.php (modified) (2 diffs)
-
includes/core/class-vefm-settings-transfer.php (modified) (1 diff)
-
includes/core/class-vefm-settings.php (modified) (1 diff)
-
readme.txt (modified) (2 diffs)
-
vefmusic.php (modified) (2 diffs)
Legend:
- Unmodified
- Added
- Removed
-
vefmusic/trunk/assets/css/vefm-admin.css
r3726330 r3755228 576 576 } 577 577 578 /* Second level: the sub-tabs of the Style screen (General, Tracks, Albums, Shows, Next show). They keep578 /* Second level: the sub-tabs of a screen — Style (General, Tracks, Albums, Shows, Next show...) and the screens that gather Free and Pro (VEFmusic | VEFmusic Pro). They keep 579 579 the classes WordPress knows (the script toggles `nav-tab-active`); only their look changes. */ 580 .vefm-admin .vefm-style-tabs.nav-tab-wrapper { 580 .vefm-admin .vefm-style-tabs.nav-tab-wrapper, 581 .vefm-admin .vefm-subtabs.nav-tab-wrapper { 581 582 display: flex; 582 583 flex-wrap: wrap; … … 587 588 } 588 589 589 .vefm-admin .vefm-style-tabs .nav-tab { 590 .vefm-admin .vefm-style-tabs .nav-tab, 591 .vefm-admin .vefm-subtabs .nav-tab { 590 592 float: none; 591 593 margin: 0; … … 601 603 602 604 .vefm-admin .vefm-style-tabs .nav-tab:hover, 603 .vefm-admin .vefm-style-tabs .nav-tab:focus { 605 .vefm-admin .vefm-style-tabs .nav-tab:focus, 606 .vefm-admin .vefm-subtabs .nav-tab:hover, 607 .vefm-admin .vefm-subtabs .nav-tab:focus { 604 608 color: var(--vefm-a-accent); 605 609 background: color-mix(in srgb, var(--wp-admin-theme-color, #2271b1) 8%, #fff); … … 608 612 .vefm-admin .vefm-style-tabs .nav-tab-active, 609 613 .vefm-admin .vefm-style-tabs .nav-tab-active:hover, 610 .vefm-admin .vefm-style-tabs .nav-tab-active:focus { 614 .vefm-admin .vefm-style-tabs .nav-tab-active:focus, 615 .vefm-admin .vefm-subtabs .nav-tab-active, 616 .vefm-admin .vefm-subtabs .nav-tab-active:hover, 617 .vefm-admin .vefm-subtabs .nav-tab-active:focus { 611 618 color: #fff; 612 619 background: var(--vefm-a-accent); 613 620 border-color: var(--vefm-a-accent); 614 621 } 622 623 .vefm-subpanel[hidden] { 624 display: none; 625 } -
vefmusic/trunk/assets/css/vefm-buttons.css
r3746875 r3755228 12 12 * 13 13 * Adjustable from Style > General (or custom CSS): 14 * --vefm-button-bg background (default: main color) 15 * --vefm-button-text-color text and icons 14 16 * --vefm-btn-hover-opacity hover/focus strength (default .85) 15 17 * --vefm-btn-disabled-opacity disabled strength (default .6) … … 27 29 .vefm-ratings-submit { 28 30 border: 0; 29 background: var( --vefm- accent, var( --wp--preset--color--primary, #1e1e1e) );31 background: var( --vefm-button-bg, var( --vefm-accent, var( --wp--preset--color--primary, #1e1e1e ) ) ); 30 32 color: var( --vefm-button-text-color, var( --wp--preset--color--background, #fff ) ); 31 33 cursor: pointer; … … 39 41 .vefm-concert-ticket-link:focus, 40 42 .vefm-concert-ticket-link:active { 41 background: var( --vefm- accent, var( --wp--preset--color--primary, #1e1e1e) );43 background: var( --vefm-button-bg, var( --vefm-accent, var( --wp--preset--color--primary, #1e1e1e ) ) ); 42 44 color: var( --vefm-button-text-color, var( --wp--preset--color--background, #fff ) ); 43 45 text-decoration: none; -
vefmusic/trunk/assets/css/vefm-frontend.css
r3746875 r3755228 622 622 flex: 0 0 auto; 623 623 display: inline-flex; 624 justify-content: center;625 margin: 0 auto;626 624 gap: 6px; 627 625 border-radius: 20px; … … 757 755 border: 0; 758 756 border-radius: 50%; 759 background: var( --vefm- accent, var( --wp--preset--color--primary, #1e1e1e) );757 background: var( --vefm-button-bg, var( --vefm-accent, var( --wp--preset--color--primary, #1e1e1e ) ) ); 760 758 color: var( --vefm-button-text-color, var( --wp--preset--color--background, #fff ) ); 761 759 line-height: 1; … … 770 768 .vefm-album-cover-flip .vefm-album-cover-toggle:focus, 771 769 .vefm-album-cover-flip .vefm-album-cover-toggle:active { 772 background: var( --vefm- accent, var( --wp--preset--color--primary, #1e1e1e) );770 background: var( --vefm-button-bg, var( --vefm-accent, var( --wp--preset--color--primary, #1e1e1e ) ) ); 773 771 color: var( --vefm-button-text-color, var( --wp--preset--color--background, #fff ) ); 774 772 } -
vefmusic/trunk/assets/css/vefm-lightbox.css
r3746875 r3755228 103 103 border: 0; 104 104 border-radius: 50%; 105 background: var( --vefm- accent, var( --wp--preset--color--primary, #1e1e1e) );105 background: var( --vefm-button-bg, var( --vefm-accent, var( --wp--preset--color--primary, #1e1e1e ) ) ); 106 106 color: var( --vefm-button-text-color, var( --wp--preset--color--background, #fff ) ); 107 107 line-height: 1; … … 116 116 .vefm-lightbox .vefm-lightbox-button:focus, 117 117 .vefm-lightbox .vefm-lightbox-button:active { 118 background: var( --vefm- accent, var( --wp--preset--color--primary, #1e1e1e) );118 background: var( --vefm-button-bg, var( --vefm-accent, var( --wp--preset--color--primary, #1e1e1e ) ) ); 119 119 color: var( --vefm-button-text-color, var( --wp--preset--color--background, #fff ) ); 120 120 } -
vefmusic/trunk/includes/class-vefm-admin-help.php
r3746875 r3755228 451 451 'overview', 452 452 __( 'Overview', 'vefmusic' ), 453 self::p( __( 'The simplest way to match the plugin to your site, valid everywhere (Gutenberg, Divi 5 and Elementor). Five sub-tabs: General, Tracks, Albums, Shows and Next show — each one adjustable separately.', 'vefmusic' ) )454 . self::p( __( 'A value left empty keeps the default. The main color, the font and the button text colorset here are shared with VEFmusic Pro (cart, donations): no need to set them twice.', 'vefmusic' ) )453 self::p( __( 'The simplest way to match the plugin to your site, valid everywhere (Gutenberg, Divi 5 and Elementor). Six sub-tabs: General, Buttons, Tracks, Albums, Shows and Next show — each one adjustable separately.', 'vefmusic' ) ) 454 . self::p( __( 'A value left empty keeps the default. The main color, the font and the button colors set here are shared with VEFmusic Pro (cart, donations): no need to set them twice.', 'vefmusic' ) ) 455 455 ), 456 456 self::topic( … … 461 461 array( __( 'Main color', 'vefmusic' ), __( 'the accent color of the blocks.', 'vefmusic' ) ), 462 462 array( __( 'Font', 'vefmusic' ), __( 'one default font for the whole site. Left empty, the blocks use the font of your theme.', 'vefmusic' ) ), 463 ) 464 ) 465 ), 466 self::topic( 467 'buttons', 468 __( 'Buttons sub-tab', 'vefmusic' ), 469 self::terms( 470 array( 471 array( __( 'Button colors', 'vefmusic' ), __( 'background, text, and the same two when the pointer is over a button, for all the buttons at once. Use them to reproduce the buttons of your theme. A color left empty keeps the default: the main color for the background, the theme\'s background color for the text, and on hover your theme\'s own button hover colors if it has any. A color you set always wins over the theme.', 'vefmusic' ) ), 463 472 array( __( 'Button shadow', 'vefmusic' ), __( 'one shadow for all the buttons. No color chosen means no shadow: the button style of your theme is kept.', 'vefmusic' ) ), 464 473 array( __( 'Button states', 'vefmusic' ), __( 'every button has the same look, only its shape differs. Set how much a button fades when the pointer is over it (or it has keyboard focus) and when it is disabled. Empty fields keep the defaults: 85% and 60%.', 'vefmusic' ) ), -
vefmusic/trunk/includes/class-vefm-admin-ui.php
r3726330 r3755228 297 297 echo '</div>'; 298 298 } 299 300 /** 301 * One screen per subject: prints the content of a screen as one or several panels. A panel is 302 * a part of the screen (for instance "VEFmusic" and "VEFmusic Pro" on the Help screen). With a 303 * single panel the content is printed as it is, with nothing around it — so a site without Pro 304 * sees exactly what it always saw. With several, a row of pills switches between the panels, 305 * and a link ending with "#vefm-sub-{screen}-{key}" opens the matching panel directly. 306 * 307 * The panels of other plugins are added with the filter 'vefm_subpanels_{screen}'. 308 * 309 * @param string $screen Short name of the screen ("help", "diagnostic"...). 310 * @param array<string,array<string,mixed>> $panels Panel key => 'label' (string), 'callback' (callable). 311 * @return void 312 */ 313 public static function render_subpanels( $screen, array $panels ) { 314 $screen = sanitize_key( $screen ); 315 /** 316 * Adds panels to a screen. Each panel: 'label' (string) and 'callback' (callable printing the 317 * content, without the page header and without closing the page). 318 * 319 * @param array $panels Panel key => label, callback. 320 */ 321 $panels = apply_filters( 'vefm_subpanels_' . $screen, $panels ); 322 323 if ( 1 === count( $panels ) ) { 324 $panel = reset( $panels ); 325 call_user_func( $panel['callback'] ); 326 return; 327 } 328 329 echo '<h2 class="nav-tab-wrapper vefm-subtabs">'; 330 $first = true; 331 foreach ( $panels as $key => $panel ) { 332 printf( 333 '<a href="#vefm-sub-%1$s-%2$s" class="nav-tab%3$s">%4$s</a>', 334 esc_attr( $screen ), 335 esc_attr( sanitize_key( $key ) ), 336 $first ? ' nav-tab-active' : '', 337 esc_html( $panel['label'] ) 338 ); 339 $first = false; 340 } 341 echo '</h2>'; 342 343 $first = true; 344 foreach ( $panels as $key => $panel ) { 345 printf( 346 '<div id="vefm-sub-%1$s-%2$s" class="vefm-subpanel"%3$s>', 347 esc_attr( $screen ), 348 esc_attr( sanitize_key( $key ) ), 349 $first ? '' : ' hidden' 350 ); 351 call_user_func( $panel['callback'] ); 352 echo '</div>'; 353 $first = false; 354 } 355 356 VEFM_Admin::enqueue_inline_script( 357 <<<'JS' 358 jQuery( function ( $ ) { 359 var $links = $( '.vefm-subtabs a' ); 360 function show( target ) { 361 $links.removeClass( 'nav-tab-active' ).filter( function () { 362 return $( this ).attr( 'href' ) === target; 363 } ).addClass( 'nav-tab-active' ); 364 $( '.vefm-subpanel' ).attr( 'hidden', true ); 365 $( target ).removeAttr( 'hidden' ); 366 } 367 $links.on( 'click', function ( e ) { 368 e.preventDefault(); 369 var target = $( this ).attr( 'href' ); 370 show( target ); 371 if ( window.history && window.history.replaceState ) { 372 window.history.replaceState( null, '', target ); 373 } 374 } ); 375 var hash = window.location.hash; 376 if ( hash && $links.filter( function () { 377 return $( this ).attr( 'href' ) === hash; 378 } ).length ) { 379 show( hash ); 380 } 381 } ); 382 JS, 383 'vefm-subpanels', 384 array( 'jquery' ) 385 ); 386 } 299 387 } -
vefmusic/trunk/includes/class-vefm-admin.php
r3746875 r3755228 507 507 ); 508 508 if ( $pro_active ) { 509 $parametres_tabs['vefmusic-pro-style'] = __( 'Pro Style', 'vefmusic' );509 // Pro Style is now a sub-tab of Style (added by VEFmusic Pro, see the 'vefm_style_tabs' action). 510 510 $parametres_tabs['vefmusic-pro-license'] = __( 'License', 'vefmusic' ); 511 511 } … … 517 517 $vente_tabs = array(); 518 518 if ( $pro_active ) { 519 // What the owner opens every day (the sales and their figures) comes first; the settings 520 // of the sales (payment, invoicing, shipping) follow. 519 521 $vente_tabs = array( 522 'vefmusic-pro-orders' => __( 'Completed sales', 'vefmusic' ), 523 'vefmusic-pro-revenue' => __( 'Statistics', 'vefmusic' ), 520 524 'vefmusic-pro-payment' => __( 'Payment', 'vefmusic' ), 521 525 'vefmusic-pro-invoicing' => __( 'Invoicing', 'vefmusic' ), … … 529 533 } 530 534 $marketing_tabs['vefmusic-press-kit'] = __( 'Press kit', 'vefmusic' ); 531 if ( $pro_active ) {532 // v2.11.0 (import VEFpressKit —) : formulaire de533 // contact/historique des demandes/statistiques de534 // téléchargement/liens limités/liste presse/kits multiples du535 // kit presse, basculés en Pro.536 $marketing_tabs['vefmusic-pro-press-kit'] = __( 'Press kit (Pro)', 'vefmusic' );537 }538 535 $marketing_tabs['vefmusic-ratings'] = __( 'Visitor ratings', 'vefmusic' ); 539 536 $marketing_tabs['vefmusic-stats'] = __( 'Listening stats', 'vefmusic' ); 540 if ( $pro_active ) {541 $marketing_tabs['vefmusic-pro-revenue'] = __( 'Statistics', 'vefmusic' );542 $marketing_tabs['vefmusic-pro-orders'] = __( 'Completed sales', 'vefmusic' );543 }544 537 545 538 $aide_tabs = array( 546 539 'vefmusic-help' => __( 'Help', 'vefmusic' ), 547 540 ); 548 if ( $pro_active ) {549 $aide_tabs['vefmusic-pro-help'] = __( 'Pro Help', 'vefmusic' );550 }551 541 $aide_tabs['vefmusic-support'] = __( 'Support & feature requests', 'vefmusic' ); 552 542 $aide_tabs['vefmusic-about'] = __( 'About', 'vefmusic' ); 553 543 $aide_tabs['vefmusic-diagnostic'] = __( 'Diagnostics', 'vefmusic' ); 554 if ( $pro_active ) {555 $aide_tabs['vefmusic-pro-diagnostic'] = __( 'Pro Diagnostics', 'vefmusic' );556 }557 544 558 545 // Order of the pages of the menu: what the owner works on first comes first (the menu entry … … 1008 995 'style_accent' => sanitize_text_field( wp_unslash( $_POST['style_accent'] ?? '' ) ), 1009 996 'style_button_text_color' => sanitize_text_field( wp_unslash( $_POST['style_button_text_color'] ?? '' ) ), 997 // 2.16.29: button background and hover colors. 998 'style_button_bg_color' => sanitize_text_field( wp_unslash( $_POST['style_button_bg_color'] ?? '' ) ), 999 'style_button_hover_bg_color' => sanitize_text_field( wp_unslash( $_POST['style_button_hover_bg_color'] ?? '' ) ), 1000 'style_button_hover_text_color' => sanitize_text_field( wp_unslash( $_POST['style_button_hover_text_color'] ?? '' ) ), 1010 1001 // 2.15.51: global button shadow — see 1011 1002 // VEFM_Button_Shadow (range clamped there). … … 1142 1133 .vefm-alpha-label { font-size: 12px; color: #646970; min-width: 34px; display: inline-block; } 1143 1134 .vefm-shadow-fields { display: flex; flex-wrap: wrap; gap: 8px 16px; margin: 8px 0 0; } 1144 .vefm-shadow-field { display: inline-flex; flex-direction: column; gap: 2px; font-size: 12px; color: #646970; }', 1135 .vefm-shadow-field { display: inline-flex; flex-direction: column; gap: 2px; font-size: 12px; color: #646970; } 1136 .vefm-button-color { margin: 0 0 12px; } 1137 .vefm-button-color label { display: block; margin-bottom: 4px; font-weight: 600; } 1138 .vefm-style-savebar[hidden] { display: none; } 1139 .vefm-style-savebar, .vefmpro-style-panel > form > .submit { position: sticky; bottom: 0; z-index: 5; margin: 0 -1px; padding: .25rem 0; background: linear-gradient( to bottom, rgba( 255, 255, 255, 0 ), #fff 35% ); } 1140 .vefm-style-savebar .submit, .vefmpro-style-panel > form > .submit { margin: 0; padding: .6rem 0; }', 1145 1141 'vefm-style-page-css' 1146 1142 ); … … 1495 1491 self::render_page_header( __( 'Diagnostics', 'vefmusic' ) ); 1496 1492 self::render_group_tabs( 'parametres', 'vefmusic-diagnostic' ); 1497 $this->render_diagnostic_tab(); 1493 VEFM_Admin_UI::render_subpanels( 1494 'diagnostic', 1495 array( 1496 'free' => array( 1497 'label' => 'VEFmusic', 1498 'callback' => array( $this, 'render_diagnostic_tab' ), 1499 ), 1500 ) 1501 ); 1498 1502 echo '</div>'; 1499 1503 } … … 1505 1509 self::render_page_header( __( 'Help', 'vefmusic' ) ); 1506 1510 self::render_group_tabs( 'aide', 'vefmusic-help' ); 1507 $this->render_help_tab(); 1511 VEFM_Admin_UI::render_subpanels( 1512 'help', 1513 array( 1514 'free' => array( 1515 'label' => 'VEFmusic', 1516 'callback' => array( $this, 'render_help_tab' ), 1517 ), 1518 ) 1519 ); 1508 1520 echo '</div>'; 1509 1521 } … … 1565 1577 <h2 class="nav-tab-wrapper vefm-style-tabs"> 1566 1578 <a href="#vefm-style-general" class="nav-tab nav-tab-active"><?php esc_html_e( 'General', 'vefmusic' ); ?></a> 1579 <a href="#vefm-style-buttons" class="nav-tab"><?php esc_html_e( 'Buttons', 'vefmusic' ); ?></a> 1567 1580 <a href="#vefm-style-tracks" class="nav-tab"><?php esc_html_e( 'Tracks', 'vefmusic' ); ?></a> 1568 1581 <a href="#vefm-style-albums" class="nav-tab"><?php esc_html_e( 'Albums', 'vefmusic' ); ?></a> 1569 1582 <a href="#vefm-style-concerts" class="nav-tab"><?php esc_html_e( 'Shows', 'vefmusic' ); ?></a> 1570 1583 <a href="#vefm-style-featured-concert" class="nav-tab"><?php esc_html_e( 'Next show', 'vefmusic' ); ?></a> 1584 <?php 1585 /** 1586 * Lets an add-on (VEFmusic Pro) add its own sub-tab to the Style screen. 1587 * The matching panel is printed by the 'vefm_style_panels' action, after the form. 1588 */ 1589 do_action( 'vefm_style_tabs' ); 1590 ?> 1571 1591 </h2> 1572 1592 … … 1585 1605 </tr> 1586 1606 <tr> 1587 <th><label for="style_ button_text_color"><?php esc_html_e( 'Button text color', 'vefmusic' ); ?></label></th>1607 <th><label for="style_font_family"><?php esc_html_e( 'Font', 'vefmusic' ); ?></label></th> 1588 1608 <td> 1589 <input type="hidden" id="style_button_text_color" name="style_button_text_color" value="<?php echo esc_attr( $s['style_button_text_color'] ); ?>" class="vefm-color-field" data-default-color="" /> 1590 <p class="description"><?php esc_html_e( 'Text and icons of every VEFmusic button (and VEFmusic Pro\'s) — unchecked follows the theme\'s background color, white by default.', 'vefmusic' ); ?></p> 1609 <input type="text" id="style_font_family" name="style_font_family" value="<?php echo esc_attr( $s['style_font_family'] ); ?>" class="regular-text" placeholder="'Poppins', sans-serif" /> 1610 <p class="description"> 1611 <?php esc_html_e( 'Optional — the theme\'s font already applies by default if this field is left empty. Enter it as in CSS: name in single quotes, then a fallback font (e.g. \'Poppins\', sans-serif).', 'vefmusic' ); ?> 1612 <br /> 1613 <?php esc_html_e( 'Finer control is possible directly in Divi: every VEFmusic module has its own Design > Text tab, with a real native Divi font picker (Google Fonts included) — already working, nothing to configure here. This field is only useful if you want one default font shared across the whole site, without setting it module by module.', 'vefmusic' ); ?> 1614 </p> 1615 </td> 1616 </tr> 1617 </table> 1618 </div> 1619 1620 <div id="vefm-style-buttons" class="vefm-style-panel" hidden> 1621 <p class="description"><?php esc_html_e( 'The look of every VEFmusic button (and VEFmusic Pro\'s). Leave a field empty and nothing is forced: the button keeps the plugin\'s default look and, on hover, your theme\'s own button hover style if it has one. Fill a field and your choice wins over the theme, on every button.', 'vefmusic' ); ?></p> 1622 <table class="form-table"> 1623 <tr> 1624 <th><?php esc_html_e( 'Button colors', 'vefmusic' ); ?></th> 1625 <td> 1626 <?php 1627 $vefm_button_colors = array( 1628 'style_button_bg_color' => __( 'Background', 'vefmusic' ), 1629 'style_button_text_color' => __( 'Text', 'vefmusic' ), 1630 'style_button_hover_bg_color' => __( 'Background on hover', 'vefmusic' ), 1631 'style_button_hover_text_color' => __( 'Text on hover', 'vefmusic' ), 1632 ); 1633 foreach ( $vefm_button_colors as $vefm_button_color_key => $vefm_button_color_label ) : 1634 ?> 1635 <div class="vefm-button-color"> 1636 <label for="<?php echo esc_attr( $vefm_button_color_key ); ?>"><?php echo esc_html( $vefm_button_color_label ); ?></label> 1637 <input type="hidden" id="<?php echo esc_attr( $vefm_button_color_key ); ?>" name="<?php echo esc_attr( $vefm_button_color_key ); ?>" value="<?php echo esc_attr( $s[ $vefm_button_color_key ] ); ?>" class="vefm-color-field" data-default-color="" /> 1638 </div> 1639 <?php endforeach; ?> 1640 <p class="description"><?php esc_html_e( 'Colors of every VEFmusic button (and VEFmusic Pro\'s), to match the buttons of your theme. A field left empty keeps the default: the background follows the main color, the text follows the theme\'s background color (white by default), and on hover your theme\'s own button hover colors apply if it has any, along with the opacity set in Button states. A color you set here always wins over the theme.', 'vefmusic' ); ?></p> 1591 1641 </td> 1592 1642 </tr> … … 1636 1686 </td> 1637 1687 </tr> 1638 <tr>1639 <th><label for="style_font_family"><?php esc_html_e( 'Font', 'vefmusic' ); ?></label></th>1640 <td>1641 <input type="text" id="style_font_family" name="style_font_family" value="<?php echo esc_attr( $s['style_font_family'] ); ?>" class="regular-text" placeholder="'Poppins', sans-serif" />1642 <p class="description">1643 <?php esc_html_e( 'Optional — the theme\'s font already applies by default if this field is left empty. Enter it as in CSS: name in single quotes, then a fallback font (e.g. \'Poppins\', sans-serif).', 'vefmusic' ); ?>1644 <br />1645 <?php esc_html_e( 'Finer control is possible directly in Divi: every VEFmusic module has its own Design > Text tab, with a real native Divi font picker (Google Fonts included) — already working, nothing to configure here. This field is only useful if you want one default font shared across the whole site, without setting it module by module.', 'vefmusic' ); ?>1646 </p>1647 </td>1648 </tr>1649 1688 </table> 1650 1689 </div> … … 1874 1913 </div> 1875 1914 1876 <?php submit_button( __( 'Save', 'vefmusic' ) ); ?> 1915 <div class="vefm-style-savebar"> 1916 <?php submit_button( __( 'Save', 'vefmusic' ) ); ?> 1917 </div> 1877 1918 </form> 1878 1919 <?php 1920 /** 1921 * Prints the panels of the sub-tabs added with 'vefm_style_tabs'. They sit OUTSIDE the form of 1922 * this screen: each one carries its own form, its own nonce and its own save button, so a 1923 * save never touches the settings of another panel. Each panel is a <div> with the classes 1924 * "vefm-style-panel" and the attribute data-vefm-own-form, and starts hidden. 1925 */ 1926 do_action( 'vefm_style_panels' ); 1879 1927 $vefm_opacity_label = esc_js( __( 'Opacity', 'vefmusic' ) ); 1880 1928 $vefm_style_js = <<<'JS' … … 1981 2029 } ); 1982 2030 1983 // Sous-onglets internes à cette page — un seul formulaire, un 1984 // seul bouton Enregistrer en bas, quel que soit l’onglet actif 1985 // (tous les champs restent dans le DOM, juste masqués). 2031 // Sous-onglets internes à cette page. Les panneaux du formulaire Free 2032 // partagent un seul bouton Enregistrer (tous les champs restent dans le 2033 // DOM, juste masqués) ; un panneau ajouté par un module (data-vefm-own-form) 2034 // a son propre formulaire et son propre bouton : la barre Enregistrer de 2035 // Free est alors masquée pour ne pas laisser croire qu’elle l’enregistre. 2036 function vefmShowStylePanel( target ) { 2037 var $panel = $( target ); 2038 $( '.vefm-style-tabs a' ).removeClass( 'nav-tab-active' ).filter( function () { 2039 return $( this ).attr( 'href' ) === target; 2040 } ).addClass( 'nav-tab-active' ); 2041 $( '.vefm-style-panel' ).attr( 'hidden', true ); 2042 $panel.removeAttr( 'hidden' ); 2043 $( '.vefm-style-savebar' ).prop( 'hidden', $panel.is( '[data-vefm-own-form]' ) ); 2044 } 1986 2045 $( '.vefm-style-tabs a' ).on( 'click', function ( e ) { 1987 2046 e.preventDefault(); 1988 2047 var target = $( this ).attr( 'href' ); 1989 $( '.vefm-style-tabs a' ).removeClass( 'nav-tab-active');1990 $( this ).addClass( 'nav-tab-active' );1991 $( '.vefm-style-panel' ).attr( 'hidden', true);1992 $( target ).removeAttr( 'hidden' );2048 vefmShowStylePanel( target ); 2049 if ( window.history && window.history.replaceState ) { 2050 window.history.replaceState( null, '', target ); 2051 } 1993 2052 } ); 2053 // Unsaved changes: the save bar stays visible at the bottom of the screen, and leaving 2054 // the page after a change (not yet saved) asks for confirmation. The state of each form 2055 // is compared with the one taken once the page, colour pickers included, is ready — 2056 // the colour pickers set their hidden field by script, which fires no event. 2057 var vefmForms = $( '.vefm-style-savebar' ).closest( 'form' ).add( '.vefmpro-style-panel form' ); 2058 var vefmSnap = []; 2059 $( window ).on( 'load', function () { 2060 vefmForms.each( function ( i ) { 2061 vefmSnap[ i ] = $( this ).serialize(); 2062 } ); 2063 } ); 2064 var vefmSaving = false; 2065 vefmForms.on( 'submit', function () { 2066 vefmSaving = true; 2067 } ); 2068 $( window ).on( 'beforeunload', function ( e ) { 2069 if ( vefmSaving ) { 2070 return; 2071 } 2072 var dirty = false; 2073 vefmForms.each( function ( i ) { 2074 if ( undefined !== vefmSnap[ i ] && $( this ).serialize() !== vefmSnap[ i ] ) { 2075 dirty = true; 2076 } 2077 } ); 2078 if ( dirty ) { 2079 e.preventDefault(); 2080 return ''; 2081 } 2082 } ); 2083 // Direct link to a sub-tab (e.g. the old Pro Style address redirects here). 2084 var vefmHash = window.location.hash; 2085 if ( vefmHash && $( '.vefm-style-tabs a' ).filter( function () { 2086 return $( this ).attr( 'href' ) === vefmHash; 2087 } ).length ) { 2088 vefmShowStylePanel( vefmHash ); 2089 } 1994 2090 } ); 1995 2091 JS; … … 2432 2528 * que le lien entre l’onglet et le rendu réel. 2433 2529 */ 2434 p rivatefunction render_diagnostic_tab() {2530 public function render_diagnostic_tab() { 2435 2531 VEFM_Diagnostic::render(); 2436 2532 } 2437 2533 2438 p rivatefunction render_help_tab() {2534 public function render_help_tab() { 2439 2535 $groups = self::get_groups(); 2440 2536 … … 2657 2753 <p class="description"> 2658 2754 <?php if ( class_exists( 'VEFM_Pro' ) && VEFM_Pro::is_active() ) : ?> 2659 <?php echo wp_kses_post( sprintf( /* translators: %s: li en vers l'onglet Press kit (Pro) */ __( 'An optional contact form before download, download statistics, ready-made PDF templates, limited-use links, a press contact list, and additional independent kits are all available with VEFmusic Pro — see the %s tab.', 'vefmusic' ), '<a href="' . esc_url( admin_url( 'admin.php?page=vefmusic-pro-press-kit' ) ) . '">' . esc_html__( 'Press kit (Pro)', 'vefmusic' ) . '</a>' ) ); ?>2755 <?php echo wp_kses_post( sprintf( /* translators: %s: link to the VEFmusic Pro panel of the Press kit screen */ __( 'An optional contact form before download, download statistics, ready-made PDF templates, limited-use links, a press contact list, and additional independent kits are all available with VEFmusic Pro — see the %s panel of this screen.', 'vefmusic' ), '<a href="' . esc_url( admin_url( 'admin.php?page=vefmusic-press-kit#vefm-sub-press-kit-pro' ) ) . '">' . esc_html__( 'VEFmusic Pro', 'vefmusic' ) . '</a>' ) ); ?> 2660 2756 <?php else : ?> 2661 2757 <?php esc_html_e( 'An optional contact form before download, download statistics, ready-made PDF templates, limited-use links, a press contact list, and additional independent kits are all available with VEFmusic Pro — see the About tab for details.', 'vefmusic' ); ?> … … 2720 2816 <p class="description"><?php esc_html_e( 'Tracks and Albums sub-tabs: background and text colors of each track, main (accent) color, VU meter peak color, gap between tracks, padding inside each track and corner radius. A value left empty keeps the default.', 'vefmusic' ); ?></p> 2721 2817 <p class="description"><?php esc_html_e( 'Block titles (album, shows) use the theme\'s heading size and weight by default. A title size set in VEFmusic > Settings > Style replaces that size for the blocks concerned.', 'vefmusic' ); ?></p> 2722 <p class="description"><?php esc_html_e( 'The --vefm-accent, --vefm-font-family and --vefm-button-text-color variables set here are shared with VEFmusic Pro (cart, donations) — no need to set them twice.', 'vefmusic' ); ?></p>2818 <p class="description"><?php esc_html_e( 'The --vefm-accent, --vefm-font-family, --vefm-button-bg and --vefm-button-text-color variables set here are shared with VEFmusic Pro (cart, donations) — no need to set them twice.', 'vefmusic' ); ?></p> 2723 2819 <p class="description"><?php esc_html_e( 'Button shadow (General sub-tab): one shadow for all buttons of VEFmusic and VEFmusic Pro — horizontal and vertical offset, blur, spread and color with opacity. No color chosen = no shadow, the theme\'s button style is kept. Icon-only controls (volume, lyrics, quantity) never get it. PayPal buttons are drawn by PayPal itself and can\'t receive it.', 'vefmusic' ); ?></p> 2724 2820 <p class="description"><?php esc_html_e( 'For the font, two options: set it once for the whole site in VEFmusic > Settings > Style (General tab), or more finely block by block directly in Divi — every VEFmusic module has its own Design > Text tab with a real native Divi font picker (Google Fonts included), already available with nothing to configure.', 'vefmusic' ); ?></p> … … 2729 2825 <li><strong><?php esc_html_e( 'Divi 5', 'vefmusic' ); ?></strong> — <?php esc_html_e( 'module\'s Advanced tab > Custom CSS, with the same variables. The show poster\'s height now adjusts automatically to the content, no setting needed.', 'vefmusic' ); ?> 2730 2826 <ul class="vefm-list vefm-list--circle"> 2731 <li><?php esc_html_e( 'Shared (all blocks)', 'vefmusic' ); ?> — <code>--vefm-accent</code>, <code>--vefm-font-family</code>, <code>--vefm-button-shadow</code>, <code>--vefm-button- text-color</code>, <code>--vefm-btn-hover-opacity</code>, <code>--vefm-btn-disabled-opacity</code></li>2827 <li><?php esc_html_e( 'Shared (all blocks)', 'vefmusic' ); ?> — <code>--vefm-accent</code>, <code>--vefm-font-family</code>, <code>--vefm-button-shadow</code>, <code>--vefm-button-bg</code>, <code>--vefm-button-text-color</code>, <code>--vefm-btn-hover-opacity</code>, <code>--vefm-btn-disabled-opacity</code></li> 2732 2828 <li><?php esc_html_e( 'Font sizes (all blocks)', 'vefmusic' ); ?> — <code>--vefm-font-size-small</code>, <code>--vefm-font-size-normal</code>, <code>--vefm-font-size-medium</code>, <code>--vefm-font-size-large</code>, <code>--vefm-font-size-x-large</code>, <code>--vefm-font-size-xx-large</code> <?php esc_html_e( '(fallback scale, only used where the active theme doesn\'t define its own font size presets — and always for the show date badge. Shared with VEFmusic Pro).', 'vefmusic' ); ?></li> 2733 2829 <li><?php esc_html_e( 'Tracks / Album (player) / Random Player', 'vefmusic' ); ?> — <code>--vefm-vu-peak</code>, <code>--vefm-track-bg</code>, <code>--vefm-track-text</code>, <code>--vefm-track-padding</code>, <code>--vefm-track-radius</code>, <code>--vefm-track-gap</code> <?php esc_html_e( '(Random Player has no dedicated Style tab of its own — it reuses --vefm-track-bg, --vefm-track-text and --vefm-track-padding from the Tracks sub-tab, not the others; set those to change how the Random Player looks).', 'vefmusic' ); ?></li> -
vefmusic/trunk/includes/class-vefm-press-kit-admin.php
r3746875 r3755228 77 77 VEFM_Admin::render_group_tabs( 'marketing', 'vefmusic-press-kit' ); 78 78 79 // Editing an additional kit (VEFmusic Pro) takes the whole screen: no panels around it. 80 /** 81 * Lets VEFmusic Pro print the whole screen (the editor of an additional kit) and return true. 82 * 83 * @param bool $printed Whether a screen was printed. 84 */ 85 if ( isset( $_GET['kit'] ) && apply_filters( 'vefm_press_kit_custom_page', false ) ) { // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- plain navigation, nothing is saved. 86 echo '</div>'; 87 return; 88 } 89 90 // One screen per subject: the press kit of VEFmusic Pro is a panel of this screen. 91 VEFM_Admin_UI::render_subpanels( 92 'press-kit', 93 array( 94 'free' => array( 95 'label' => 'VEFmusic', 96 'callback' => array( $this, 'render_body' ), 97 ), 98 ) 99 ); 100 101 echo '</div>'; 102 } 103 104 /** 105 * Content of the press kit screen of VEFmusic (a panel of the screen). 106 */ 107 public function render_body() { 79 108 if ( isset( $_GET['vefm_msg'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- lecture seule d'un message de confirmation, aucune action. 80 109 $type = isset( $_GET['vefm_msg_type'] ) && 'error' === sanitize_key( wp_unslash( $_GET['vefm_msg_type'] ) ) ? 'error' : 'success'; // phpcs:ignore WordPress.Security.NonceVerification.Recommended … … 111 140 $this->render_pro_upsell_notice(); 112 141 } 113 114 echo '</div>';115 142 } 116 143 -
vefmusic/trunk/includes/core/class-vefm-button-shadow.php
r3726330 r3755228 117 117 * @param string[] $selectors CSS selectors, one button type each. 118 118 */ 119 $selectors = apply_filters( 'vefm_button_shadow_selectors', self::SELECTORS ); 120 $clean = array(); 121 foreach ( (array) $selectors as $selector ) { 122 // A selector never needs braces, semicolons, at-rules or 123 // markup: stripping them keeps a filtered value from breaking 124 // out of the rule. 125 $selector = trim( preg_replace( '/[{};@<\\\\]/', '', wp_strip_all_tags( (string) $selector ) ) ); 126 if ( '' !== $selector ) { 127 $clean[] = $selector; 128 } 129 } 130 return array_values( array_unique( $clean ) ); 119 return VEFM_Button_States::clean_selectors( apply_filters( 'vefm_button_shadow_selectors', self::SELECTORS ) ); 131 120 } 132 121 -
vefmusic/trunk/includes/core/class-vefm-button-states.php
r3746875 r3755228 1 1 <?php 2 2 /** 3 * Global button states (hover and disabled strength ).3 * Global button states (hover and disabled strength, hover colors). 4 4 * 5 5 * Every VEFmusic button shares one look (assets/css/vefm-buttons.css); … … 8 8 * 9 9 * - hover / keyboard-focus opacity (--vefm-btn-hover-opacity); 10 * - disabled opacity (--vefm-btn-disabled-opacity). 10 * - disabled opacity (--vefm-btn-disabled-opacity); 11 * - background and text color of a filled button on hover / keyboard focus 12 * (printed as rules, only when set, see build_css()). 11 13 * 12 14 * Plain values in, CSS out, like VEFM_Button_Shadow, so VEFmusic Pro … … 45 47 'disabled' => 60, 46 48 ); 49 50 /** 51 * Cleans a list of selectors coming from a filter: a selector never 52 * needs braces, semicolons, at-rules or markup, and stripping them keeps 53 * a filtered value from breaking out of the rule. 54 * 55 * @param mixed $selectors Selectors, one button type each. 56 * @return string[] Unique, cleaned selectors. 57 */ 58 public static function clean_selectors( $selectors ) { 59 $clean = array(); 60 foreach ( (array) $selectors as $selector ) { 61 $selector = trim( preg_replace( '/[{};@<\\\\]/', '', wp_strip_all_tags( (string) $selector ) ) ); 62 if ( '' !== $selector ) { 63 $clean[] = $selector; 64 } 65 } 66 return array_values( array_unique( $clean ) ); 67 } 68 69 /** 70 * Filled buttons, the ones that take a background and a hover color: 71 * the Free ones plus those added by other plugins (VEFmusic Pro) 72 * through the filter. Outlined buttons and icon-only controls are left 73 * out: a background on hover would turn them into filled ones. 74 * 75 * @return string[] Cleaned selectors. 76 */ 77 public static function get_filled_selectors() { 78 /** 79 * Filters the filled buttons that receive the hover colors. 80 * 81 * @since 2.16.29 82 * 83 * @param string[] $selectors CSS selectors, one button type each. 84 */ 85 return self::clean_selectors( apply_filters( 'vefm_button_filled_selectors', VEFM_Button_Shadow::SELECTORS ) ); 86 } 87 88 /** 89 * Sanitizes one color for printing: hex, rgb()/hsl(), var(--x) and 90 * named colors pass, anything else (quotes, braces, semicolons) is dropped. 91 * 92 * @param mixed $raw Saved value. 93 * @return string Safe color, or '' when empty. 94 */ 95 public static function sanitize_color( $raw ) { 96 return trim( preg_replace( '/[^#a-zA-Z0-9(),.%\s-]/', '', (string) $raw ) ); 97 } 47 98 48 99 /** … … 87 138 * override the default carried by vefm-buttons.css. 88 139 * 89 * @param array $settings Keys: hover, disabled (percent or ''). 90 * @return string CSS rule. 140 * @param array $settings Keys: hover, disabled (percent or ''), hover_bg, 141 * hover_text (color or ''). 142 * @return string CSS rules. 91 143 */ 92 144 public static function build_css( array $settings ) { … … 101 153 } 102 154 } 103 return '' === $vars ? '' : ':root{' . $vars . '}'; 155 $css = '' === $vars ? '' : ':root{' . $vars . '}'; 156 157 // Hover / keyboard-focus colors of the filled buttons. One rule per 158 // selector (an invalid selector would drop a grouped rule for every 159 // button); ":root" raises the specificity above each component's own 160 // hover rule, so the setting wins everywhere. 161 $declarations = ''; 162 $hover_bg = isset( $settings['hover_bg'] ) ? self::sanitize_color( $settings['hover_bg'] ) : ''; 163 $hover_text = isset( $settings['hover_text'] ) ? self::sanitize_color( $settings['hover_text'] ) : ''; 164 if ( '' !== $hover_bg ) { 165 $declarations .= 'background:' . $hover_bg . ';'; 166 } 167 if ( '' !== $hover_text ) { 168 $declarations .= 'color:' . $hover_text . ';'; 169 } 170 if ( '' !== $declarations ) { 171 foreach ( self::get_filled_selectors() as $selector ) { 172 $css .= ':root ' . $selector . ':is(:hover,:focus-visible):not(:disabled,.vefm-play--disabled){' . $declarations . '}'; 173 } 174 } 175 return $css; 104 176 } 105 177 … … 107 179 * Reads the saved settings. 108 180 * 109 * @return array Keys: hover, disabled .181 * @return array Keys: hover, disabled, hover_bg, hover_text. 110 182 */ 111 183 public static function get_settings() { 112 184 return array( 113 'hover' => VEFM_Settings::get( 'style_button_hover_opacity', '' ), 114 'disabled' => VEFM_Settings::get( 'style_button_disabled_opacity', '' ), 185 'hover' => VEFM_Settings::get( 'style_button_hover_opacity', '' ), 186 'disabled' => VEFM_Settings::get( 'style_button_disabled_opacity', '' ), 187 'hover_bg' => VEFM_Settings::get( 'style_button_hover_bg_color', '' ), 188 'hover_text' => VEFM_Settings::get( 'style_button_hover_text_color', '' ), 115 189 ); 116 190 } -
vefmusic/trunk/includes/core/class-vefm-renderer.php
r3746875 r3755228 200 200 'fontFamily' => VEFM_Settings::get( 'style_font_family', '' ), 201 201 'buttonTextColor' => VEFM_Settings::get( 'style_button_text_color', '' ), 202 'buttonBgColor' => VEFM_Settings::get( 'style_button_bg_color', '' ), 202 203 ) 203 204 ); … … 408 409 // même principe accentColor ci-dessus, partagé avec Pro. 409 410 'buttonTextColor' => '--vefm-button-text-color', 411 // 2.16.29: button background (empty = main color). 412 'buttonBgColor' => '--vefm-button-bg', 410 413 'vuPeakColor' => '--vefm-vu-peak', 411 414 'concertBadgeColor' => '--vefm-concert-badge', -
vefmusic/trunk/includes/core/class-vefm-settings-transfer.php
r3746875 r3755228 86 86 // export (setting added 15/09/2026, list not updated). 87 87 'style_button_text_color', 88 'style_button_bg_color', 89 'style_button_hover_bg_color', 90 'style_button_hover_text_color', 88 91 'style_button_shadow_color', 89 92 'style_button_shadow_x', -
vefmusic/trunk/includes/core/class-vefm-settings.php
r3746875 r3755228 152 152 // séparé, même principe déjà établi pour ces deux-là. 153 153 'style_button_text_color' => '', 154 // 2.16.29: button background and hover colors. Empty = unchanged 155 // look (background follows the main color, no color change on hover). 156 'style_button_bg_color' => '', 157 'style_button_hover_bg_color' => '', 158 'style_button_hover_text_color' => '', 154 159 // 2.15.51: global button shadow. Empty color = no 155 160 // shadow at all (theme button styles untouched); empty -
vefmusic/trunk/readme.txt
r3746875 r3755228 6 6 Tested up to: 7.1 7 7 Requires PHP: 8.3 8 Stable tag: 2.16. 278 Stable tag: 2.16.30 9 9 License: GPLv2 or later 10 10 License URI: https://www.gnu.org/licenses/gpl-2.0.html … … 125 125 == Changelog == 126 126 127 = 2.16.30 = 128 * New: Style: the Save button stays visible at the bottom of the screen, and leaving the page with unsaved changes asks for confirmation. 129 * Changed: Style: the button settings (colors, shadow, states) have their own "Buttons" sub-tab. Same settings, nothing is lost. 130 * Changed: Style > Buttons now says what follows your theme and what the plugin forces: a field left empty keeps the default look and the theme's own hover style; a color you set always wins. 131 * Changed: one screen per subject. Help, Diagnostics and Press kit can now carry the content of VEFmusic Pro in a second panel of the same screen, and the Pro style settings become a Style sub-tab. Without Pro, nothing changes. 132 133 = 2.16.29 = 134 * New: Style > General > Button colors. Set the background, the text, the background on hover and the text on hover of all the buttons (VEFmusic Pro's included) to reproduce the buttons of your theme. A field left empty keeps the current look: the background follows the main color and nothing changes color on hover. The button text color setting now lives in this group. 135 * Changed: the buttons share their background and hover rules in fewer places, so the stylesheets are lighter and easier to maintain. No visual change. 136 137 = 2.16.28 = 138 * Fix: removed redundant centering rules on the cart and "Buy the full album" buttons. No visual change. 139 127 140 = 2.16.27 = 128 141 * Maintenance: code comments cleaned up. No change in behavior. -
vefmusic/trunk/vefmusic.php
r3746875 r3755228 3 3 * Plugin Name: VEFmusic 4 4 * Description: Free plugin for a band’s website: audio player, album showcase, show calendar, visitor ratings, SEO structured data. Compatible with Gutenberg, Divi 5 and Elementor, no shortcode. No sales features — see VEFmusic Pro (v-images.com) to sell tracks/albums/merch, manage ticketing or accept donations. 5 * Version: 2.16. 275 * Version: 2.16.30 6 6 * Requires at least: 6.0 7 7 * Requires PHP: 8.3 … … 55 55 // --------------------------------------------------------------------------- 56 56 57 define( 'VEFM_VERSION', '2.16. 27' );57 define( 'VEFM_VERSION', '2.16.30' ); 58 58 define( 'VEFM_PLUGIN_FILE', __FILE__ ); 59 59 define( 'VEFM_PLUGIN_DIR', plugin_dir_path( __FILE__ ) );
Note:
See TracChangeset
for help on using the changeset viewer.
![(please configure the [header_logo] section in trac.ini)](/chrome/site/your_project_logo.png)