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
-
-
-
',
- '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() {
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(){} );
}
);