|
| 1 | +import { |
| 2 | + cimo, i18n, ajaxUrl, |
| 3 | +} from 'stackable' |
| 4 | +import { createRoot } from '~stackable/util' |
| 5 | + |
| 6 | +import { __ } from '@wordpress/i18n' |
| 7 | +import { Dashicon } from '@wordpress/components' |
| 8 | +import domReady from '@wordpress/dom-ready' |
| 9 | +import { |
| 10 | + useState, useRef, useEffect, |
| 11 | +} from '@wordpress/element' |
| 12 | +import { models } from '@wordpress/api' |
| 13 | + |
| 14 | +const CimoDownloadNotice = props => { |
| 15 | + const [ data, setData ] = useState( { status: cimo?.status, action: cimo?.action } ) |
| 16 | + const pollCountRef = useRef( 0 ) |
| 17 | + |
| 18 | + const onDismiss = () => { |
| 19 | + const settings = new models.Settings( { stackable_hide_cimo_notice: true } ) // eslint-disable-line camelcase |
| 20 | + settings.save() |
| 21 | + |
| 22 | + if ( cimo ) { |
| 23 | + cimo.hideNotice = true |
| 24 | + } |
| 25 | + |
| 26 | + // Update the global stackable.cimo hideNotice variable |
| 27 | + if ( typeof window !== 'undefined' && window.stackable?.cimo ) { |
| 28 | + window.stackable.cimo.hideNotice = true |
| 29 | + } |
| 30 | + |
| 31 | + props?.onDismiss?.() |
| 32 | + } |
| 33 | + |
| 34 | + // Polls the Cimo plugin status to detect installation or activation state changes |
| 35 | + const pollStatus = ( action, link, pollOnce = false ) => { |
| 36 | + fetch( ajaxUrl, { |
| 37 | + method: 'POST', |
| 38 | + headers: { 'Content-Type': 'application/x-www-form-urlencoded' }, |
| 39 | + body: new URLSearchParams( { |
| 40 | + action: 'stackable_check_cimo_status', |
| 41 | + // eslint-disable-next-line camelcase |
| 42 | + user_action: action, |
| 43 | + nonce: cimo.nonce, |
| 44 | + } ), |
| 45 | + credentials: 'same-origin', |
| 46 | + } ).then( res => res.json() ).then( res => { |
| 47 | + if ( ! res.success ) { |
| 48 | + setData( { status: 'error', action: '' } ) |
| 49 | + |
| 50 | + const errorMessage = res?.data?.message ? res.data.message : 'Server error' |
| 51 | + |
| 52 | + throw new Error( 'Stackable: ' + errorMessage ) |
| 53 | + } |
| 54 | + |
| 55 | + if ( pollCountRef.current === 0 && link ) { |
| 56 | + window.open( link, '_blank' ) |
| 57 | + } |
| 58 | + |
| 59 | + pollCountRef.current += 1 |
| 60 | + |
| 61 | + const _data = res.data |
| 62 | + |
| 63 | + if ( data.status !== _data.status ) { |
| 64 | + setData( _data ) |
| 65 | + |
| 66 | + // Update the global stackable.cimo status/action variables |
| 67 | + // so new image block selections reflect the latest Cimo installation state |
| 68 | + if ( typeof window !== 'undefined' && window.stackable?.cimo ) { |
| 69 | + window.stackable.cimo.status = _data.status |
| 70 | + window.stackable.cimo.action = _data.action |
| 71 | + } |
| 72 | + } |
| 73 | + |
| 74 | + // Stop polling if it has reached 3 attempts, or plugin status indicates installation/activation is complete |
| 75 | + if ( pollOnce || pollCountRef.current >= 3 || |
| 76 | + ( action === 'install' && ( _data.status === 'installed' || _data.status === 'activated' ) ) || |
| 77 | + ( action === 'activate' && _data.status === 'activated' ) |
| 78 | + ) { |
| 79 | + return |
| 80 | + } |
| 81 | + |
| 82 | + setTimeout( () => { |
| 83 | + pollStatus( action ) |
| 84 | + }, 3000 * pollCountRef.current ) |
| 85 | + } ).catch( e => { |
| 86 | + // eslint-disable-next-line no-console |
| 87 | + console.error( e.message ) |
| 88 | + } ) |
| 89 | + } |
| 90 | + |
| 91 | + useEffect( () => { |
| 92 | + const _media = wp.media |
| 93 | + const old = _media.view.MediaFrame.Select |
| 94 | + |
| 95 | + // When the media library closes, check and update the Cimo plugin status |
| 96 | + // to ensure the UI reflects the latest installation or activation state. |
| 97 | + _media.view.MediaFrame.Select = old.extend( { |
| 98 | + initialize() { |
| 99 | + old.prototype.initialize.apply( this, arguments ) |
| 100 | + |
| 101 | + this.on( 'close', () => { |
| 102 | + pollCountRef.current = 0 |
| 103 | + if ( data.status === 'activated' ) { |
| 104 | + return |
| 105 | + } |
| 106 | + |
| 107 | + if ( data.status === 'not_installed' ) { |
| 108 | + pollStatus( 'install', null, true ) |
| 109 | + return |
| 110 | + } |
| 111 | + |
| 112 | + pollStatus( 'activate', null, true ) |
| 113 | + } ) |
| 114 | + }, |
| 115 | + } ) |
| 116 | + }, [] ) |
| 117 | + |
| 118 | + const onActionClick = e => { |
| 119 | + e.preventDefault() |
| 120 | + pollCountRef.current = 0 |
| 121 | + |
| 122 | + if ( data.status === 'not_installed' ) { |
| 123 | + setData( { status: 'installing', action: '' } ) |
| 124 | + pollStatus( 'install', e.currentTarget.href ) |
| 125 | + return |
| 126 | + } |
| 127 | + |
| 128 | + setData( { status: 'activating', action: '' } ) |
| 129 | + pollStatus( 'activate', e.currentTarget.href ) |
| 130 | + } |
| 131 | + |
| 132 | + return ( <> |
| 133 | + <button aria-label="dismiss" onClick={ onDismiss }><Dashicon icon="no" /></button> |
| 134 | + { data.status === 'activated' |
| 135 | + ? <p> |
| 136 | + { __( 'Cimo Image Optimizer has been activated. Please refresh this page to begin optimizing your images automatically.', i18n ) } |
| 137 | + </p> |
| 138 | + : <p> { __( 'Instantly optimize images as you upload them with Cimo Image Optimizer.', i18n ) } |
| 139 | + |
| 140 | + { data.status === 'installing' |
| 141 | + ? <span> { __( 'Installing', i18n ) }</span> |
| 142 | + : ( data.status === 'activating' |
| 143 | + ? <span>{ __( 'Activating', i18n ) } </span> |
| 144 | + : <a href={ data.action } target="_blank" rel="noreferrer" onClick={ onActionClick }> |
| 145 | + { data.status === 'installed' ? __( 'Activate now', i18n ) : __( 'Install now', i18n ) } |
| 146 | + </a> |
| 147 | + ) |
| 148 | + } |
| 149 | + </p> |
| 150 | + } |
| 151 | + </> ) |
| 152 | +} |
| 153 | + |
| 154 | +const CimoDownloadNoticeWrapper = props => { |
| 155 | + return <div className="stk-cimo-notice"> <CimoDownloadNotice { ...props } /> </div> |
| 156 | +} |
| 157 | + |
| 158 | +export default CimoDownloadNoticeWrapper |
| 159 | + |
| 160 | +domReady( () => { |
| 161 | + if ( ! cimo || cimo.status === 'activated' || cimo.hideNotice || |
| 162 | + typeof wp === 'undefined' || ! wp?.media?.view?.Attachment?.Details |
| 163 | + ) { |
| 164 | + return |
| 165 | + } |
| 166 | + |
| 167 | + const CurrentDetailsView = wp.media.view.Attachment.Details |
| 168 | + |
| 169 | + // Display the Cimo download notice in the media library |
| 170 | + const CustomDetailsView = CurrentDetailsView.extend( { |
| 171 | + render() { |
| 172 | + const result = CurrentDetailsView.prototype.render.apply( this, arguments ) |
| 173 | + |
| 174 | + if ( cimo?.hideNotice ) { |
| 175 | + return result |
| 176 | + } |
| 177 | + |
| 178 | + const details = this.el.querySelector( '.attachment-info .details' ) |
| 179 | + if ( details && ! this.el.querySelector( '.stk-cimo-notice' ) ) { |
| 180 | + const noticeDiv = document.createElement( 'div' ) |
| 181 | + noticeDiv.className = 'stk-cimo-notice' |
| 182 | + |
| 183 | + const onDismiss = () => { |
| 184 | + if ( noticeDiv && noticeDiv.parentNode ) { |
| 185 | + noticeDiv.parentNode.removeChild( noticeDiv ) |
| 186 | + } |
| 187 | + } |
| 188 | + |
| 189 | + createRoot( noticeDiv ).render( <CimoDownloadNotice onDismiss={ onDismiss } /> ) |
| 190 | + details.insertAdjacentElement( 'afterend', noticeDiv ) |
| 191 | + } |
| 192 | + |
| 193 | + return result |
| 194 | + }, |
| 195 | + } ) |
| 196 | + |
| 197 | + wp.media.view.Attachment.Details = CustomDetailsView |
| 198 | +} ) |
0 commit comments