is_plugin_screen() ) { return; } /** * Filter whether the helpdesk support assistant is shown on Forumax admin pages. * * @param bool $enabled False when "Hide Support Chat" is on in the settings. */ if ( ! apply_filters( 'forumax_support_assistant_enabled', ! $this->is_hidden_in_settings() ) ) { return; } $this->is_active = true; wp_enqueue_style( 'forumax-support-assistant', FORUMAX_ASSETS . 'admin/css/support-assistant.css', [], FORUMAX_VERSION ); wp_enqueue_script( 'forumax-support-assistant', FORUMAX_ASSETS . 'admin/js/support-assistant.js', [], FORUMAX_VERSION, true ); // Spinner shown in the panel until the helpdesk page has loaded. wp_add_inline_style( 'forumax-support-assistant', '.forumax-support-assistant .chatbox-iframe-wraper.forumax-loading{background:#fff} .forumax-support-assistant .chatbox-iframe-wraper.forumax-loading::after{content:"";position:absolute;top:50%;left:50%;width:32px;height:32px;margin:-16px 0 0 -16px;border:3px solid #e2e8f0;border-top-color:#0866ff;border-radius:50%;animation:forumax-support-spin .8s linear infinite} @keyframes forumax-support-spin{to{transform:rotate(360deg)}}' ); // Load the iframe on first open only. To make that feel instant: // - hovering the button opens the connection to the helpdesk (DNS/TLS // only, no data is sent), which saves ~1s on a cold connection; // - loading starts on press rather than when the click completes. wp_add_inline_script( 'forumax-support-assistant', "(function () { var root = document.querySelector('.forumax-support-assistant'); var toggle = root && root.querySelector('.chat-toggle'); var wrap = root && root.querySelector('.chatbox-iframe-wraper'); var iframe = root && root.querySelector('iframe[data-src]'); if (!toggle || !wrap || !iframe) return; var src = iframe.getAttribute('data-src'); var warmed = false; function warm() { if (warmed) return; warmed = true; var link = document.createElement('link'); link.rel = 'preconnect'; link.href = new URL(src).origin; document.head.appendChild(link); } function load() { if (iframe.getAttribute('src')) return; warm(); wrap.classList.add('forumax-loading'); iframe.addEventListener('load', function () { wrap.classList.remove('forumax-loading'); }, { once: true }); iframe.setAttribute('src', src); } toggle.addEventListener('pointerenter', warm); toggle.addEventListener('pointerdown', load); toggle.addEventListener('click', load); })();" ); } /** * The admin's email and name, only when Freemius consent covers them. * * Consent is given by the admin who opted in, so the current user must be * that Freemius account; other admins on the same site get no pre-fill. * * @return array{email?: string, name?: string} */ private function get_consented_lead(): array { if ( ! function_exists( 'bc_fs' ) ) { return []; } $fs = bc_fs(); if ( ! is_object( $fs ) || ! method_exists( $fs, 'is_tracking_allowed' ) || ! $fs->is_registered() || ! $fs->is_tracking_allowed() ) { return []; } $fs_user = $fs->get_user(); $wp_user = wp_get_current_user(); if ( ! is_object( $fs_user ) || empty( $fs_user->email ) || 0 !== strcasecmp( $fs_user->email, $wp_user->user_email ) ) { return []; } $name = trim( ( $fs_user->first ?? '' ) . ' ' . ( $fs_user->last ?? '' ) ); return [ 'email' => sanitize_email( $fs_user->email ), 'name' => sanitize_text_field( '' !== $name ? $name : $wp_user->display_name ), ]; } /** * Build the iframe URL: product scope, plus the admin's details when consented. * * @return string */ private function get_iframe_url(): string { $args = [ 'ctx' => self::PRODUCT_CTX, 'ezd_scope' => self::DOCS_SCOPE, ]; $lead = $this->get_consented_lead(); if ( ! empty( $lead['email'] ) ) { $args['atml_email'] = $lead['email']; $args['atml_name'] = $lead['name']; } /** * Filter the query args passed to the helpdesk assistant iframe. * * @param array $args Query args (ctx, ezd_scope, and atml_email/atml_name when consented). */ $args = (array) apply_filters( 'forumax_support_assistant_args', $args ); $args = array_filter( array_map( 'strval', $args ), 'strlen' ); return add_query_arg( array_map( 'rawurlencode', $args ), self::IFRAME_URL ); } /** * Print the embed markup in the admin footer. * * @return void */ public function render_embed(): void { if ( ! $this->is_active ) { return; } ?>