diff --git a/README.md b/README.md index b798a5fd..bed03d23 100644 --- a/README.md +++ b/README.md @@ -5,7 +5,7 @@ **Requires at least:** 6.6 \ **Tested up to:** 6.9 \ **Requires PHP:** 7.4 \ -**Stable tag:** 4.1.0 \ +**Stable tag:** 4.1.1 \ **License:** GPLv2 or later Ally: Make your site more inclusive by scanning for accessibility violations, fixing them easily, and adding a usability widget and accessibility statement. @@ -227,6 +227,11 @@ You can report security bugs through the Patchstack Vulnerability Disclosure Pro ## Changelog +### 4.1.1 – 2026-03-31 + +* Tweak: Improved WPML support +* Tweak: WordPress 7.0 design compatibility + ### 4.1.0 – 2026-02-23 * New: Added bulk remediation flow to generate AI alt text or mark multiple images as decorative diff --git a/assets/css/admin.css b/assets/css/admin.css index 6ffadf82..1970c6a3 100644 --- a/assets/css/admin.css +++ b/assets/css/admin.css @@ -7,6 +7,11 @@ filter: none; } -.error-elementor { - border-left-color: #93003F; +.notice_wrapper { + border: 1px solid #ccd0d4; + box-shadow: 0 1px 4px #00000026; +} + +.notice_wrapper.error-elementor { + border-inline-start: 4px solid #93003F; } diff --git a/assets/css/notice.css b/assets/css/notice.css new file mode 100644 index 00000000..2166c661 --- /dev/null +++ b/assets/css/notice.css @@ -0,0 +1,171 @@ +:root { + --ea11y-notice-dismiss-icon: #1e1e1e; + --ea11y-notice-error: #dc2626; + --ea11y-notice-error-bg: #fde8ec; + --ea11y-notice-error-custom-border: #93003f; + --ea11y-notice-white: #fff; + --ea11y-notice-warning-bg: #fef8ee; + --ea11y-notice-warning-border: #f0b849; + --ea11y-notice-warning-btn: #bb5b1d; + --ea11y-notice-warning-btn-hover: rgb(187 91 29 / 0.08); + --ea11y-notice-success-bg: #eff9f1; + --ea11y-notice-success-border: #4ab866; + --ea11y-notice-info-bg: #f1f6fb; + --ea11y-notice-info-border: #0288d1; + --ea11y-notice-pink-border: #d8d8da; + --ea11y-notice-pink-accent: #ff7be5; + --ea11y-notice-pink-text: #444950; + --ea11y-notice-pink-link: #d004d4; + --ea11y-notice-pink-icon-bg: #fae8ff; + --ea11y-notice-heading: #0c0d0e; + --ea11y-notice-subheading: #6d7882; + --ea11y-notice-error-btn-hover: rgb(220 38 38 / 0.08); +} + +.ea11y__notice { + padding: 12px; + border: none; +} + +.ea11y__notice p { + margin: 0; +} + +.ea11y__notice .notice-dismiss::before { + content: "\f335"; + font-family: dashicons, sans-serif; + font-weight: 400; + font-size: 22px; + line-height: 24px; + color: var(--ea11y-notice-dismiss-icon); + width: 24px; +} + +.ea11y__notice button:not(.notice-dismiss) { + display: block; + padding: 0; + background: none; + color: var(--ea11y-notice-error); + border: none; + font-size: 13px; + font-style: normal; + font-weight: 400; + line-height: 1.5; + letter-spacing: -0.247px; + text-decoration-line: underline; + cursor: pointer; +} + +.ea11y__notice--error { + background-color: var(--ea11y-notice-error-bg); + border-inline-start: 4px solid var(--ea11y-notice-error); +} + +.ea11y__notice--error-custom { + background-color: var(--ea11y-notice-white); + border-inline-start: 4px solid var(--ea11y-notice-error-custom-border); +} + +.ea11y__notice--warning { + background-color: var(--ea11y-notice-warning-bg); + border-inline-start: 4px solid var(--ea11y-notice-warning-border); +} + +.ea11y__notice--success { + background-color: var(--ea11y-notice-success-bg); + border-inline-start: 4px solid var(--ea11y-notice-success-border); +} + +.ea11y__notice--info { + background-color: var(--ea11y-notice-info-bg); + border-inline-start: 4px solid var(--ea11y-notice-info-border); +} + +.ea11y__renewal-notice { + border-inline-start: none; +} + +.ea11y__notice--pink { + padding-left: 54px; + position: relative; + background-color: var(--ea11y-notice-white); + border: 1px solid var(--ea11y-notice-pink-border); + border-inline-start: 4px solid var(--ea11y-notice-pink-accent); +} + +.ea11y__notice--pink b { + font-weight: 500; + color: var(--ea11y-notice-pink-text); +} + +.ea11y__notice--pink a { + font-weight: 500; + color: var(--ea11y-notice-pink-link); + margin-inline-start: 10px; + text-decoration: none; +} + +.ea11y__notice--pink .ea11y__icon-block { + display: flex; + justify-content: center; + align-items: center; + width: 48px; + position: absolute; + left: 0; + top: 0; + bottom: 0; + background-color: var(--ea11y-notice-pink-icon-bg); +} + +.ea11y__notice .primary-heading { + font-size: 17px; + color: var(--ea11y-notice-heading); + font-weight: 700; + margin-bottom: 8px; +} + +.ea11y__notice .sub-heading { + font-size: 13px; + color: var(--ea11y-notice-subheading); + margin-top: 0; + margin-bottom: 12px; +} + +/** Renewal notice styles **/ + +.ea11y__content-block { + display: flex; + gap: 15px; +} + +.ea11y__content-block .ea11y__notice-content { + display: flex; + flex-direction: column; + align-items: flex-start; + gap: 10px; +} + +.ea11y__renewal-notice-btn { + text-decoration: none; + padding: 4px 10px; + border-radius: 4px; + width: auto; +} + +.ea11y__renewal-notice.ea11y__notice--warning .ea11y__renewal-notice-btn { + color: var(--ea11y-notice-warning-btn); + border: 1px solid var(--ea11y-notice-warning-btn); +} + +.ea11y__renewal-notice.ea11y__notice--error .ea11y__renewal-notice-btn { + color: var(--ea11y-notice-error); + border: 1px solid var(--ea11y-notice-error); +} + +.ea11y__renewal-notice.ea11y__notice--warning .ea11y__renewal-notice-btn:hover { + background: var(--ea11y-notice-warning-btn-hover); +} + +.ea11y__renewal-notice.ea11y__notice--error .ea11y__renewal-notice-btn:hover { + background-color: var(--ea11y-notice-error-btn-hover); +} diff --git a/classes/utils.php b/classes/utils.php index 38df00c0..ec86f3f0 100644 --- a/classes/utils.php +++ b/classes/utils.php @@ -15,7 +15,21 @@ public static function get_api_client(): ?Client { public static function is_plugin_settings_page(): bool { $current_screen = get_current_screen(); - return str_contains( $current_screen->id, '_page_accessibility-settings' ); + return $current_screen && str_contains( $current_screen->id, '_page_accessibility-settings' ); + } + + public static function is_wp_dashboard_page(): bool { + $current_screen = get_current_screen(); + return $current_screen && 'dashboard' === $current_screen->id; + } + + public static function is_wp_settings_page(): bool { + $current_screen = get_current_screen(); + return $current_screen && 'options-general' === $current_screen->id; + } + + public static function is_plugin_page(): bool { + return self::is_plugin_settings_page(); } public static function is_elementor_installed() :bool { diff --git a/classes/utils/notice-base.php b/classes/utils/notice-base.php index 4a1e56db..5b8cc9e2 100644 --- a/classes/utils/notice-base.php +++ b/classes/utils/notice-base.php @@ -157,7 +157,8 @@ public function handle_dismiss() { } public function render() { - echo sprintf( '
%s%s
', + return sprintf( '%s%s
', __( 'New accessibility plugin available!', 'pojo-accessibility' ), __( 'Your current plugin is no longer supported. Switch to Ally - Web Accessibility now to access more customization, control, and tools for a more inclusive site.', 'pojo-accessibility' ), Upgrade::get_learn_more_link( 'acc-notice-switch-oc' ), // link to learn more diff --git a/modules/settings/module.php b/modules/settings/module.php index 02ea3526..106c7867 100644 --- a/modules/settings/module.php +++ b/modules/settings/module.php @@ -632,6 +632,7 @@ public function register_notices( Notices $notice_manager ) { $notices = [ 'Quota_80', 'Quota_100', + 'Renewal_Notice', ]; foreach ( $notices as $notice ) { diff --git a/modules/settings/notices/quota-100.php b/modules/settings/notices/quota-100.php index 75760718..0f02beec 100644 --- a/modules/settings/notices/quota-100.php +++ b/modules/settings/notices/quota-100.php @@ -23,8 +23,8 @@ class Quota_100 extends Notice_Base { public function content(): string { $plan = Settings::get( Settings::PLAN_DATA )->plan->name; - if ( $plan === 'Free' ) { - return sprintf( '%s
', + if ( 'Free' === $plan ) { + return sprintf( '%s
', __( 'You’ve reached your free plan limit', 'pojo-accessibility' ), __( 'Upgrade to scan more pages, unlock AI fixes, and access all accessibility features.', 'pojo-accessibility' ), SettingsModule::get_upgrade_link( 'acc-100-quota' ), @@ -32,7 +32,7 @@ public function content(): string { ); } - return sprintf( '%s
', + return sprintf( '%s
', __( 'You’ve reached your monthly plan usage', 'pojo-accessibility' ), __( 'Upgrade now to raise your limit and maintain complete access to all accessibility features.', 'pojo-accessibility' ), SettingsModule::get_upgrade_link( 'acc-100-quota' ), diff --git a/modules/settings/notices/renewal-notice.php b/modules/settings/notices/renewal-notice.php new file mode 100644 index 00000000..0eff1046 --- /dev/null +++ b/modules/settings/notices/renewal-notice.php @@ -0,0 +1,225 @@ +diff( $given_date ); + $this->days_diff = $interval->invert ? -$interval->days : $interval->days; + return $this->days_diff; + } + + private function get_notice_icon( $type ) { + if ( 'warning' === $type ) { + return ''; + } + if ( 'error' === $type ) { + return ''; + } + return ''; + } + + public function get_renewal_text(): array { + if ( $this->days_diff <= 30 && $this->days_diff > 0 ) { + return [ + 'title' => esc_html__( 'Ally Subscription Ending Soon!', 'pojo-accessibility' ), + 'description' => esc_html__( 'Renew now to keep access to Ally Assistant and continue improving your website\'s accessibility with guided fixes and scans.', 'pojo-accessibility' ), + 'btn' => esc_html__( 'Enable Auto-Renew', 'pojo-accessibility' ), + 'link' => esc_url( SettingsModule::get_upgrade_link( 'acc-renew-30' ) ), + 'type' => 'warning', + ]; + } + if ( $this->days_diff <= 0 && $this->days_diff > -7 ) { + return [ + 'title' => esc_html__( 'Your Ally subscription has expired', 'pojo-accessibility' ), + 'description' => esc_html__( 'Ally Assistant is no longer active. Renew now to resume accessibility scans and step by step fixes for your site.', 'pojo-accessibility' ), + 'btn' => esc_html__( 'Renew Now', 'pojo-accessibility' ), + 'link' => esc_url( SettingsModule::get_upgrade_link( 'acc-renew-expire' ) ), + 'type' => 'error', + ]; + } + return [ + 'title' => esc_html__( "It's not too late - renew Ally", 'pojo-accessibility' ), + 'description' => esc_html__( "Reactivate your subscription to restore Ally Assistant and continue improving your website's accessibility.", 'pojo-accessibility' ), + 'btn' => esc_html__( 'Reactivate Now', 'pojo-accessibility' ), + 'link' => esc_url( SettingsModule::get_upgrade_link( 'acc-renew-post-expire' ) ), + 'type' => 'error', + ]; + } + + /** + * Inner HTML for the renewal notice (icon + title + description + CTA). + */ + public function content(): string { + if ( null === $this->days_diff ) { + return ' '; + } + $text = $this->get_renewal_text(); + $this->type = $text['type']; + $icon = $this->get_notice_icon( $text['type'] ); + return sprintf( + '