diff --git a/readme.txt b/readme.txt index 032416a..8de1c7c 100644 --- a/readme.txt +++ b/readme.txt @@ -5,7 +5,7 @@ Requires at least: 4.8 Donate Link: https://givewp.com/ Tested up to: 6.5 Requires PHP: 7.4 -Stable tag: 2.0.4 +Stable tag: 2.0.5 License: GPLv3 License URI: http://www.gnu.org/licenses/gpl-3.0.html @@ -106,6 +106,11 @@ This is the first version of this plugin. It is a tool for your convenience. Rol == Changelog == += 2.0.5 = +* New: In this version we've brought back the "trunk" option to rollback to. This allows plugin or theme developers who use trunk for beta testing to rollback to the latest trunk version. Thanks, @megamenu for suggesting this be brought back. +* Fix: Refactored how plugin avatar images are checked so that all available image types and sizes are checked. This resolves an issue where some plugins would not display an avatar image. +* Fix: On the final rollback confirmation screen, the plugin name field was outputting raw HTML. This has been fixed to properly display the plugin name, even if it contains some html characters. + = 2.0.4 = * Fix: Resolved issue REST route not including proper permission callback which created a PHP notice. Thanks, @rom1our for submitting the issue. * Fix: Resolve issue with REST API and multisite installs not being able to properly communicate with the endpoint. diff --git a/src/TrunkPopover.js b/src/TrunkPopover.js new file mode 100644 index 0000000..b99c0bb --- /dev/null +++ b/src/TrunkPopover.js @@ -0,0 +1,28 @@ +import { useState } from '@wordpress/element'; +import { Dashicon, Popover } from '@wordpress/components'; +import { __ } from '@wordpress/i18n'; + +function TrunkPopover() { + const [ isPopoverVisible, setIsPopoverVisible ] = useState( false ); + + const showPopover = () => { + setIsPopoverVisible(true); + }; + + const hidePopover = () => { + setIsPopoverVisible(false); + }; + + return ( +
+ + {isPopoverVisible && ( + + {__( 'Trunk is where the most current revisions of the code should be stored, often representing the development version of the software. This is particularly relevant for developers and testers who are working with the very latest code changes that have not yet been released to the public.', 'wp-rollback' )} + + )} +
+ ); +} + +export default TrunkPopover; diff --git a/src/admin.js b/src/admin.js index 8f92ecd..06d2c65 100644 --- a/src/admin.js +++ b/src/admin.js @@ -1,11 +1,12 @@ import './admin.scss'; -import { Button, Dashicon, Modal, Spinner } from '@wordpress/components'; +import { Button, Dashicon, Modal, Popover, Spinner } from '@wordpress/components'; import { render, useEffect, useState } from '@wordpress/element'; import { __, _n, sprintf } from '@wordpress/i18n'; import domReady from '@wordpress/dom-ready'; import { decodeEntities } from '@wordpress/html-entities'; import { getQueryArgs } from '@wordpress/url'; import ExpandableText from './ExpandableText'; +import TrunkPopover from './TrunkPopover'; const AdminPage = () => { @@ -27,9 +28,9 @@ const AdminPage = () => { let restUrl = `${wprData.restUrl}wp-rollback/v1/fetch-info/?type=${queryArgs.type}&slug=${queryArgs.type === 'theme' ? queryArgs.theme_file : queryArgs.plugin_slug}`; - const headers = new Headers({ - 'X-WP-Nonce': wprData.restApiNonce // Assuming nonce is stored in wprData.nonce - }); + const headers = new Headers( { + 'X-WP-Nonce': wprData.restApiNonce, // Assuming nonce is stored in wprData.nonce + } ); fetch( restUrl, { headers: headers } ) .then( ( response ) => response.json() ) @@ -40,38 +41,38 @@ const AdminPage = () => { .catch( ( error ) => { console.error( 'Error fetching data:', error ); } ); - }, [wprData] ); - - useEffect( () => { - if ( rollbackInfo && rollbackInfo.slug ) { // Check if rollbackInfo is loaded and has a slug - checkImage( `https://ps.w.org/${rollbackInfo.slug}/assets/icon-128x128.png`, ( exists ) => { - if ( exists ) { - setImageUrl( `https://ps.w.org/${rollbackInfo.slug}/assets/icon-128x128.png` ); - } else { - checkImage( `https://ps.w.org/${rollbackInfo.slug}/assets/icon-128x128.jpg`, ( exists ) => { - if ( exists ) { - setImageUrl( `https://ps.w.org/${rollbackInfo.slug}/assets/icon-128x128.jpg` ); - } else { - checkImage( `https://ps.w.org/${rollbackInfo.slug}/assets/icon-128x128.gif`, ( exists ) => { - if ( exists ) { - setImageUrl( `https://ps.w.org/${rollbackInfo.slug}/assets/icon-128x128.gif` ); - } else { - setImageUrl( wprData.avatarFallback ); - } - } ); + }, [ wprData ] ); + + useEffect(() => { + const checkAndSetImage = async () => { + if (rollbackInfo && rollbackInfo.slug) { + const sizes = ['icon-256x256', 'icon-128x128', 'icon']; + const extensions = ['png', 'jpg', 'gif', 'svg']; + + for (let size of sizes) { + for (let ext of extensions) { + const url = `https://ps.w.org/${rollbackInfo.slug}/assets/${size}.${ext}`; + const exists = await checkImage(url); + if (exists) { + setImageUrl(url); + return; } - } ); + } } - } ); - } - }, [ rollbackInfo ] ); - - // @TODO: Refactor to remove this function because the API should return false if the image doesn't exist. - function checkImage( url, callback ) { - var img = new Image(); - img.onload = () => callback( true ); - img.onerror = () => callback( false ); - img.src = url; + setImageUrl(wprData.avatarFallback); + } + }; + + checkAndSetImage(); + }, [rollbackInfo]); + + function checkImage(url) { + return new Promise((resolve, reject) => { + var img = new Image(); + img.onload = () => resolve(true); + img.onerror = () => resolve(false); + img.src = url; + }); } if ( isLoading ) { @@ -184,7 +185,7 @@ const AdminPage = () => { {queryArgs.type === 'plugin' && ( {decodeEntities( rollbackInfo.name )} @@ -194,7 +195,7 @@ const AdminPage = () => { {queryArgs.type === 'theme' && ( {decodeEntities( rollbackInfo.name )} @@ -262,11 +263,14 @@ const AdminPage = () => {
{Object.keys( rollbackInfo.versions ) - .filter( version => version !== 'trunk' ) // remove 'trunk' - .sort( ( a, b ) => b.localeCompare( a, undefined, { - numeric : true, - sensitivity: 'base', - } ) ) // reverse the order + .sort((a, b) => { + if (a === 'trunk') return 1; // Always places 'trunk' at the end + if (b === 'trunk') return -1; // Always places 'trunk' at the end + return b.localeCompare(a, undefined, { + numeric: true, + sensitivity: 'base', + }); + }) .map( ( version, index ) => (
@@ -278,11 +282,13 @@ const AdminPage = () => { onChange={() => setIsRollbackVersion( version )} // Add this line /> {version} - {( queryArgs.current_version === version ) && ( version !== 'trunk' ) && ( + {( queryArgs.current_version === version ) && ( {__( 'Currently Installed', 'wp-rollback' )} )} - + {( 'trunk' === version ) && ( + + )}
@@ -337,7 +343,9 @@ const AdminPage = () => { htmlFor="tablecell">{queryArgs.type === 'plugin' ? __( 'Plugin Name:', 'wp-rollback' ) : __( 'Theme Name:', 'wp-rollback' )} - {rollbackInfo.name} + @@ -388,8 +396,6 @@ const AdminPage = () => { className={'wpr-button-cancel'}>{__( 'Cancel', 'wp-rollback' )} - - )} diff --git a/src/admin.scss b/src/admin.scss index f852f69..45de488 100644 --- a/src/admin.scss +++ b/src/admin.scss @@ -53,7 +53,8 @@ $container-width: 802px; height: auto; margin: 0 0 25px; } - p{ + + p { margin: 0; padding: 0; } @@ -265,32 +266,39 @@ $container-width: 802px; &.wpr-active-row { background: #F1F8FF; } + + .wpr-popover-wrap { + display: inline-block; + margin-left: 10px; + } } +// Radios listing versions .wpr-version-radio-wrap { margin: 0; padding: 0; label { - display: block; + display: flex; padding: 20px 30px; + align-items: center; } input[type="radio"] { - margin: -5px 0 0; + margin: 0; } span.wpr-version-lineitem { font-size: 18px; font-weight: 600; - margin: 0 0 6px 8px; + margin: 0 0 0 8px; } span.wpr-version-lineitem-current { font-size: 15px; font-style: italic; font-weight: 400; - margin: 0 0 6px 20px; + margin: 0 0 0 20px; } } @@ -346,9 +354,23 @@ $container-width: 802px; } +// Popover +.wpr-popover { + padding: 12px; + background: #FFF; + border: 1px solid $border-color; + box-shadow: 0 0 10px rgb(0 0 0 / 9%); + max-width: 300px; + font-size: 15px; + line-height: 1.4em; + + .components-popover__content { + width: auto; + } + +} // Loading - .wpr-loading-content { display: flex; justify-content: center; diff --git a/wp-rollback.php b/wp-rollback.php index fff9093..690503c 100644 --- a/wp-rollback.php +++ b/wp-rollback.php @@ -5,7 +5,7 @@ * Description: Rollback (or forward) any WordPress.org plugin, theme or block like a boss. * Author: WP Rollback * Author URI: https://wprollback.com/ - * Version: 2.0.4 + * Version: 2.0.5 * Text Domain: wp-rollback * Domain Path: /languages *