From 778c8db337e0df13d2fdf4c4af5452e002da751e Mon Sep 17 00:00:00 2001 From: Rodica Irodiu Date: Tue, 16 Jun 2026 12:15:02 +0300 Subject: [PATCH 1/6] Refresh Support Parrot admin UI/UX - Rebuild the settings screen with a clean, WP-native card layout (status banner, intro card, details panel, action buttons), replacing the legacy printf/inline-styled markup - Use the official Themeisle logo in the header - Show share details as right-aligned label/value rows - Make "Copy all details" the primary action with modern navigator.clipboard copy + "Copied!" feedback - Load the screen CSS/JS for the customer (not just the parrot user) - Redirect to the settings page on plugin activation - Rename plugin to "Themeisle Support Parrot" and update description - Fix stray current-time echo in get_expiration_date() - Ensure admin notices render below the header (wp-header-end marker) Co-Authored-By: Claude Opus 4.8 --- inc/css/parrot.css | 195 ++++++++++++++++++++++++++++++++++++++ inc/js/parrot.js | 64 +++++++++++++ pirate-parrot.php | 231 ++++++++++++++++++++++++++++----------------- themeisle-logo.png | Bin 0 -> 15034 bytes 4 files changed, 406 insertions(+), 84 deletions(-) create mode 100644 themeisle-logo.png diff --git a/inc/css/parrot.css b/inc/css/parrot.css index 44bdce3..6ff1fbb 100644 --- a/inc/css/parrot.css +++ b/inc/css/parrot.css @@ -1,3 +1,198 @@ +/* Support Parrot admin screen */ +.ti-parrot-wrap { + max-width: 900px; +} + +.ti-parrot-header { + display: flex; + align-items: center; + gap: 12px; + margin: 10px 0 20px; +} + +.ti-parrot-header h1 { + margin: 0; + padding: 0; + font-size: 23px; + font-weight: 600; + line-height: 1.3; +} + +.ti-parrot-logo { + width: auto; + height: 32px; + display: block; +} + +.ti-parrot-header-sep { + width: 1px; + height: 26px; + background: #c3c4c7; +} + +.ti-parrot-notice { + max-width: 720px; + margin: 0 0 16px; +} + +.ti-parrot-status { + display: flex; + align-items: center; + gap: 8px; + padding: 10px 14px; + margin-bottom: 16px; + border: 1px solid; + border-radius: 6px; + font-size: 14px; +} + +.ti-parrot-status .dashicons { + width: 20px; + height: 20px; + font-size: 20px; + flex: 0 0 auto; +} + +.ti-parrot-status--active { + background: #edfaef; + border-color: #b8e6c1; + color: #135e96; +} + +.ti-parrot-status--active .dashicons { + color: #00a32a; +} + +.ti-parrot-status--inactive { + background: #f6f7f7; + border-color: #dcdcde; + color: #50575e; +} + +.ti-parrot-status--inactive .dashicons { + color: #8c8f94; +} + +.ti-parrot-card { + background: #fff; + border: 1px solid #c3c4c7; + border-radius: 6px; + padding: 16px 20px; + margin-bottom: 16px; + box-shadow: 0 1px 1px rgba( 0, 0, 0, 0.04 ); +} + +.ti-parrot-intro p { + margin: 0 0 6px; + font-size: 14px; + line-height: 1.6; + color: #3c434a; +} + +.ti-parrot-intro p:last-child { + margin-bottom: 0; +} + +.ti-parrot-intro-hint { + color: #646970; + font-size: 13px; + font-weight: 600; +} + +.ti-parrot-details-header { + display: flex; + align-items: center; + justify-content: space-between; + gap: 10px; + margin-bottom: 4px; +} + +.ti-parrot-details-title { + font-size: 14px; + font-weight: 600; + color: #1d2327; +} + +.ti-parrot-row { + display: flex; + align-items: center; + gap: 10px; + padding: 10px 0; + border-top: 1px solid #f0f0f1; +} + +.ti-parrot-row-label { + flex: 0 0 150px; + font-size: 13px; + color: #646970; +} + +.ti-parrot-row-value { + flex: 1; + text-align: right; + font-size: 13px; + color: #1d2327; + word-break: break-all; +} + +.ti-parrot-mono { + font-family: Consolas, Monaco, monospace; +} + +.ti-parrot-copy .dashicons { + width: 18px; + height: 18px; + font-size: 18px; + vertical-align: text-bottom; +} + +.ti-parrot-copy-label { + margin-left: 4px; +} + +.ti-parrot-copy.ti-parrot-copied { + border-color: #00a32a; + color: #00a32a; +} + +.ti-parrot-copy.button-primary.ti-parrot-copied { + background: #00a32a; + border-color: #00a32a; + color: #fff; +} + +.ti-parrot-copy.button-primary.ti-parrot-copied:hover, +.ti-parrot-copy.button-primary.ti-parrot-copied:focus { + background: #00a32a; + border-color: #00a32a; + color: #fff; +} + +.ti-parrot-expiry { + margin: 12px 0 0; + font-size: 12px; + color: #646970; +} + +.ti-parrot-actions { + display: flex; + align-items: center; + gap: 10px; +} + +.ti-parrot-actions .ti-parrot-release { + color: #b32d2e; + border-color: #b32d2e; + background: #fff; +} + +.ti-parrot-actions .ti-parrot-release:hover, +.ti-parrot-actions .ti-parrot-release:focus { + color: #fff; + background: #b32d2e; + border-color: #b32d2e; +} + #pp-log-console .pp-log { overflow: hidden; } diff --git a/inc/js/parrot.js b/inc/js/parrot.js index 61c9636..9f461fc 100644 --- a/inc/js/parrot.js +++ b/inc/js/parrot.js @@ -7,6 +7,19 @@ ); function init() { + $( document ).on( + "click", ".ti-parrot-copy", function( e ){ + e.preventDefault(); + var button = this; + var text = button.getAttribute( "data-clipboard-text" ) || ""; + copyText( text ).then( + function(){ + showCopied( button ); + } + ); + } + ); + $( '#pp-flush' ).on( "click", function(e){ e.preventDefault(); @@ -83,6 +96,57 @@ ); } + function copyText( text ) { + if ( navigator.clipboard && navigator.clipboard.writeText ) { + return navigator.clipboard.writeText( text ).catch( function(){ + return legacyCopy( text ); + } ); + } + return legacyCopy( text ); + } + + function legacyCopy( text ) { + return new Promise( + function( resolve ){ + var area = document.createElement( "textarea" ); + area.value = text; + area.style.position = "fixed"; + area.style.opacity = "0"; + document.body.appendChild( area ); + area.focus(); + area.select(); + try { + document.execCommand( "copy" ); + } catch ( err ) {} + document.body.removeChild( area ); + resolve(); + } + ); + } + + function showCopied( button ) { + var $button = $( button ); + var $icon = $button.find( ".dashicons" ); + var $label = $button.find( ".ti-parrot-copy-label" ); + var prev = $label.length ? $label.text() : ""; + + $button.addClass( "ti-parrot-copied" ); + $icon.removeClass( "dashicons-clipboard" ).addClass( "dashicons-yes" ); + if ( $label.length ) { + $label.text( ( typeof pp !== "undefined" && pp.copied ) ? pp.copied : "Copied!" ); + } + + setTimeout( + function(){ + $button.removeClass( "ti-parrot-copied" ); + $icon.removeClass( "dashicons-yes" ).addClass( "dashicons-clipboard" ); + if ( $label.length ) { + $label.text( prev ); + } + }, 1600 + ); + } + function showSpinner() { $( '#pp-spinner' ).css( 'visibility', 'visible' ).attr( 'aria-hidden', 'false' ).show(); } diff --git a/pirate-parrot.php b/pirate-parrot.php index eb5f725..a227ec1 100644 --- a/pirate-parrot.php +++ b/pirate-parrot.php @@ -1,9 +1,9 @@ get_options(); add_action( 'admin_menu', array( $this, 'register_settings_page' ) ); + register_activation_hook( __FILE__, array( $this, 'wake_bird' ) ); register_deactivation_hook( __FILE__, array( $this, 'sleep_bird' ) ); add_action( 'ti_kill_parrot', array( $this, 'sleep_bird' ) ); add_action( 'init', array( $this, 'init' ) ); + add_action( 'admin_init', array( $this, 'maybe_activation_redirect' ) ); + } + + function wake_bird() { + set_transient( 'ti_parrot_activation_redirect', true, 30 ); + } + + function maybe_activation_redirect() { + if ( ! get_transient( 'ti_parrot_activation_redirect' ) ) { + return; + } + delete_transient( 'ti_parrot_activation_redirect' ); + + // Don't redirect when activating multiple plugins at once. + if ( isset( $_GET['activate-multi'] ) ) { + return; + } + + wp_safe_redirect( admin_url( 'tools.php?page=ti_pirate_parrot' ) ); + exit; } function init() { @@ -94,7 +115,8 @@ function admin_enqueue_scripts() { 'pirate-parrot', 'pp', array( - 'nonce' => wp_create_nonce( 'parrot' ), + 'nonce' => wp_create_nonce( 'parrot' ), + 'copied' => __( 'Copied!', 'pirate-parrot' ), ) ); @@ -235,9 +257,7 @@ function register_settings_page() { ) ); - if ( $this->is_user_parrot() ) { - add_action( 'load-' . $submenu, array( $this, 'load_js_and_css' ) ); - } + add_action( 'load-' . $submenu, array( $this, 'load_js_and_css' ) ); } function is_user_parrot() { @@ -283,53 +303,56 @@ function ti_parrot_cage() { // delete the account if it's expired $this->kill_sleep_bird(); } - printf( - ' - - - -
- -

%1$s

- - %7$s - -

%3$s

- - %6$s - -
- %2$s - %5$s - -
-
', - 'Themeisle Parrot', - get_submit_button( ( 'regenerate' === $token_action ? 'Recall Parrot' : 'Call Parrot' ), 'primary', 'submit', false ), - 'This plugin was made to allow a secured assistance from our support team, with no need to use your admin password. It will create a temporary admin account for our team, so they can have access to your WordPress Dashboard. This thing will be possible through a secret token, which will be generated by the plugin and which will be available for only 5 days. If our work is not finished yet, a new token will be generated for another 5 days to let us log in to your admin area again. Once our job is done, you can remove the new account or you can disable the plugin which will automatically delete the account. -All you have to do is to click on the button below for a new token. Then, give it to the moderator who has requested access, using our Private Messaging.', - esc_attr( $token_action ), - ( $account_exists ? get_submit_button( 'Release Parrot', 'delete', 'token_delete', false ) : '' ), - $this->get_parrot_info(), - $this->get_status_message( $message ) - ); + $is_active = $account_exists && isset( $this->_options['token'] ); + $primary_label = $account_exists ? __( 'Regenerate token', 'pirate-parrot' ) : __( 'Call the parrot', 'pirate-parrot' ); + ?> +
+
+ + +

+
+ +
+ + get_status_message( $message ); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- escaped within the method. ?> + + + get_expiration_date(); ?> +
+ + + + + — + + +
+ +
+ + +
+ + +
+

+

+
+ + + render_parrot_details(); ?> + + +
+ + + + + +
+
+ handle_logging(); } @@ -374,31 +397,74 @@ function init_parrot_kill() { wp_schedule_event( time(), 'twicedaily', 'ti_kill_parrot' ); } - function get_parrot_info() { - $output = ''; - if ( isset( $this->_options['token'] ) ) { - $output = sprintf( - '

%1$s

', - sprintf( - 'Parrot info:

Copy info ', - esc_html( $this->_options['token'] ), - wp_login_url(), - get_bloginfo( 'version' ), - phpversion(), - get_locale(), - wp_get_theme()->get( 'Name' ) .' '. wp_get_theme()->get( 'Version' ) - ) - ); - $output .= sprintf( - '

%1$s

', - ( ! is_wp_error( $expiration_date = $this->get_expiration_date() ) - ? 'This parrot will leave on ' . esc_html( $expiration_date ) - : $expiration_date->get_error_message() - ) - ); - } + function get_parrot_info_rows() { + $theme = wp_get_theme(); - return $output; + return array( + array( + 'label' => __( 'Access token', 'pirate-parrot' ), + 'value' => isset( $this->_options['token'] ) ? $this->_options['token'] : '', + 'mono' => true, + ), + array( + 'label' => __( 'Login URL', 'pirate-parrot' ), + 'value' => wp_login_url(), + ), + array( + 'label' => __( 'WordPress version', 'pirate-parrot' ), + 'value' => get_bloginfo( 'version' ), + ), + array( + 'label' => __( 'PHP version', 'pirate-parrot' ), + 'value' => phpversion(), + ), + array( + 'label' => __( 'Site locale', 'pirate-parrot' ), + 'value' => get_locale(), + ), + array( + 'label' => __( 'Theme', 'pirate-parrot' ), + 'value' => trim( $theme->get( 'Name' ) . ' ' . $theme->get( 'Version' ) ), + ), + ); + } + + function render_parrot_details() { + $rows = $this->get_parrot_info_rows(); + + // Build the "copy all" payload, one "Label: value" per line. + $lines = array(); + foreach ( $rows as $row ) { + $lines[] = $row['label'] . ': ' . $row['value']; + } + $copy_all = implode( "\n", $lines ); + $expiration = $this->get_expiration_date(); + ?> +
+
+ + +
+ +
+ + +
+ +

+ get_error_message() ); + } + ?> +

+
+ %1$s

', $message ); + $output = sprintf( '

%1$s

', esc_html( $message ) ); } } else { - $output = sprintf( '

%1$s

', $message->get_error_message() ); + $output = sprintf( '

%1$s

', esc_html( $message->get_error_message() ) ); } if ( '' !== $output ) { $output = sprintf( - '
- %2$s -
', - ( $is_error_message ? 'error' : 'updated' ), + '
%2$s
', + ( $is_error_message ? 'notice-error' : 'notice-success' ), $output ); } diff --git a/themeisle-logo.png b/themeisle-logo.png new file mode 100644 index 0000000000000000000000000000000000000000..6671f5f156bc49db004ed78b331b804f627c5ec0 GIT binary patch literal 15034 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 Date: Tue, 16 Jun 2026 12:25:23 +0300 Subject: [PATCH 2/6] Potential fix for pull request finding Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> --- pirate-parrot.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pirate-parrot.php b/pirate-parrot.php index a227ec1..4c1af19 100644 --- a/pirate-parrot.php +++ b/pirate-parrot.php @@ -39,7 +39,7 @@ function __construct() { } function wake_bird() { - set_transient( 'ti_parrot_activation_redirect', true, 30 ); + set_transient( 'ti_parrot_activation_redirect', true, 5 * MINUTE_IN_SECONDS ); } function maybe_activation_redirect() { From 9e3a78ca8b9ae7ea3dcfe111bd4d44b6b1ffc713 Mon Sep 17 00:00:00 2001 From: Rodica-Elena Irodiu Date: Tue, 16 Jun 2026 12:26:03 +0300 Subject: [PATCH 3/6] Potential fix for pull request finding Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> --- pirate-parrot.php | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/pirate-parrot.php b/pirate-parrot.php index 4c1af19..1ef2749 100644 --- a/pirate-parrot.php +++ b/pirate-parrot.php @@ -48,6 +48,16 @@ function maybe_activation_redirect() { } delete_transient( 'ti_parrot_activation_redirect' ); + // Avoid breaking AJAX/REST/cron requests. + if ( wp_doing_ajax() || ( defined( 'REST_REQUEST' ) && REST_REQUEST ) || ( defined( 'DOING_CRON' ) && DOING_CRON ) ) { + return; + } + + // Only redirect users who can actually access the screen. + if ( is_network_admin() || ! current_user_can( 'manage_options' ) ) { + return; + } + // Don't redirect when activating multiple plugins at once. if ( isset( $_GET['activate-multi'] ) ) { return; From 18cc7a04097c09d2e1534bb0f3ec239315e42bd9 Mon Sep 17 00:00:00 2001 From: Rodica-Elena Irodiu Date: Tue, 16 Jun 2026 12:26:42 +0300 Subject: [PATCH 4/6] Potential fix for pull request finding Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> --- pirate-parrot.php | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/pirate-parrot.php b/pirate-parrot.php index 1ef2749..9c67537 100644 --- a/pirate-parrot.php +++ b/pirate-parrot.php @@ -356,9 +356,7 @@ function ti_parrot_cage() {
- - - + 'ti-parrot-release' ) ); ?>
From 14089cb1445e03d7383d675f948f5069a0dba0b4 Mon Sep 17 00:00:00 2001 From: Rodica-Elena Irodiu Date: Tue, 16 Jun 2026 12:27:00 +0300 Subject: [PATCH 5/6] Potential fix for pull request finding Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> --- inc/js/parrot.js | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/inc/js/parrot.js b/inc/js/parrot.js index 9f461fc..ee88ef2 100644 --- a/inc/js/parrot.js +++ b/inc/js/parrot.js @@ -107,19 +107,24 @@ function legacyCopy( text ) { return new Promise( - function( resolve ){ - var area = document.createElement( "textarea" ); - area.value = text; + function( resolve, reject ){ + var area = document.createElement( "textarea" ); + var ok = false; + area.value = text; area.style.position = "fixed"; area.style.opacity = "0"; document.body.appendChild( area ); area.focus(); area.select(); try { - document.execCommand( "copy" ); + ok = document.execCommand( "copy" ); } catch ( err ) {} document.body.removeChild( area ); - resolve(); + if ( ok ) { + resolve(); + } else { + reject( new Error( "copy_failed" ) ); + } } ); } From 2aa239ef1463f34dc52f0fb11f0b5e5063b2b072 Mon Sep 17 00:00:00 2001 From: Rodica-Elena Irodiu Date: Tue, 16 Jun 2026 12:27:18 +0300 Subject: [PATCH 6/6] Potential fix for pull request finding Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> --- inc/js/parrot.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/inc/js/parrot.js b/inc/js/parrot.js index ee88ef2..e464aa9 100644 --- a/inc/js/parrot.js +++ b/inc/js/parrot.js @@ -16,7 +16,7 @@ function(){ showCopied( button ); } - ); + ).catch( function(){} ); } );