Plugin Directory

Changeset 3447574


Ignore:
Timestamp:
01/27/2026 07:49:19 AM (2 months ago)
Author:
ailab
Message:

Fix the Question btn and tree-node style; Renew the auto insert init.

Location:
readmo-ai
Files:
20 edited
10 copied

Legend:

Unmodified
Added
Removed
  • readmo-ai/tags/1.2.2/Controller/admin/class-readmo-ai-admin-settings.php

    r3447021 r3447574  
    112112        add_action( 'wp_ajax_readmo_ai_save_settings', array( $this, 'ajax_save_settings' ) );
    113113        add_action( 'wp_ajax_readmo_ai_save_auto_insert_settings', array( $this, 'ajax_save_auto_insert_settings' ) );
    114         add_action( 'wp_ajax_readmo_ai_delete_auto_insert_settings', array( $this, 'ajax_delete_auto_insert_settings' ) );
    115114    }
    116115
     
    343342                array(
    344343                    'message' => __( 'Security check failed', 'readmo-ai' ),
    345                 )
     344                ),
     345                null,
     346                JSON_UNESCAPED_UNICODE
    346347            );
    347348        }
     
    352353                array(
    353354                    'message' => __( 'Insufficient permissions', 'readmo-ai' ),
    354                 )
     355                ),
     356                null,
     357                JSON_UNESCAPED_UNICODE
    355358            );
    356359        }
     
    361364                array(
    362365                    'message' => __( 'API Key is required', 'readmo-ai' ),
    363                 )
     366                ),
     367                null,
     368                JSON_UNESCAPED_UNICODE
    364369            );
    365370        }
     
    372377                array(
    373378                    'message' => __( 'API Key cannot be empty', 'readmo-ai' ),
    374                 )
     379                ),
     380                null,
     381                JSON_UNESCAPED_UNICODE
    375382            );
    376383        }
     
    387394                array(
    388395                    'message' => __( 'Settings saved successfully', 'readmo-ai' ),
    389                 )
     396                ),
     397                null,
     398                JSON_UNESCAPED_UNICODE
    390399            );
    391400        } else {
     
    393402                array(
    394403                    'message' => __( 'Failed to save settings', 'readmo-ai' ),
    395                 )
     404                ),
     405                null,
     406                JSON_UNESCAPED_UNICODE
    396407            );
    397408        }
     
    412423                array(
    413424                    'message' => __( 'Security check failed', 'readmo-ai' ),
    414                 )
     425                ),
     426                null,
     427                JSON_UNESCAPED_UNICODE
    415428            );
    416429        }
     
    421434                array(
    422435                    'message' => __( 'Insufficient permissions', 'readmo-ai' ),
    423                 )
     436                ),
     437                null,
     438                JSON_UNESCAPED_UNICODE
    424439            );
    425440        }
     
    437452            wp_send_json_success(
    438453                array(
    439                     'message'          => __( 'Auto-insert settings saved successfully', 'readmo-ai' ),
    440                     'saved_settings'   => $auto_insert_settings,
     454                    'message'           => __( 'Auto-insert settings saved successfully', 'readmo-ai' ),
     455                    'saved_settings'    => $auto_insert_settings,
    441456                    'verified_settings' => $verified_settings,
    442                 )
     457                ),
     458                null,
     459                JSON_UNESCAPED_UNICODE
    443460            );
    444461        } else {
    445462            wp_send_json_error(
    446463                array(
    447                     'message'          => __( 'Failed to save auto-insert settings', 'readmo-ai' ),
     464                    'message'            => __( 'Failed to save auto-insert settings', 'readmo-ai' ),
    448465                    'attempted_settings' => $auto_insert_settings,
    449                 )
    450             );
    451         }
    452     }
    453 
    454     /**
    455      * AJAX handler to delete auto-insert settings
    456      *
    457      * Handles AJAX requests to remove auto-insert configuration.
    458      *
    459      * @since 1.2.0
    460      * @return void
    461      */
    462     public function ajax_delete_auto_insert_settings() {
    463         // Verify nonce.
    464         if ( ! isset( $_POST['nonce'] ) || ! wp_verify_nonce( sanitize_text_field( wp_unslash( $_POST['nonce'] ) ), 'readmo_ai_admin_nonce' ) ) {
    465             wp_send_json_error(
    466                 array(
    467                     'message' => __( 'Security check failed', 'readmo-ai' ),
    468                 )
    469             );
    470         }
    471 
    472         // Check user capabilities.
    473         if ( ! current_user_can( 'manage_options' ) ) {
    474             wp_send_json_error(
    475                 array(
    476                     'message' => __( 'Insufficient permissions', 'readmo-ai' ),
    477                 )
    478             );
    479         }
    480 
    481         // Delete settings.
    482         $deleted = $this->settings_dao->delete_auto_insert_settings();
    483 
    484         if ( $deleted ) {
    485             wp_send_json_success(
    486                 array(
    487                     'message' => __( 'Auto-insert settings removed successfully', 'readmo-ai' ),
    488                 )
    489             );
    490         } else {
    491             wp_send_json_error(
    492                 array(
    493                     'message' => __( 'Failed to remove auto-insert settings', 'readmo-ai' ),
    494                 )
     466                ),
     467                null,
     468                JSON_UNESCAPED_UNICODE
    495469            );
    496470        }
     
    513487        $settings['enabled'] = ! empty( $post_data['enabled'] );
    514488
    515         // Position.
    516         $allowed_positions    = array( 'before_content', 'after_content', 'footer' );
     489        // Position is fixed to 'after_content'.
    517490        $settings['position'] = 'after_content';
    518         if ( isset( $post_data['position'] ) && in_array( $post_data['position'], $allowed_positions, true ) ) {
    519             $settings['position'] = sanitize_text_field( $post_data['position'] );
    520         }
    521491
    522492        // Excluded post types (array of post type names).
  • readmo-ai/tags/1.2.2/Controller/frontend/class-readmo-ai-ajax-handler.php

    r3445269 r3447574  
    108108                    'error_code' => 'nonce_expired',
    109109                ),
    110                 400
     110                400,
     111                JSON_UNESCAPED_UNICODE
    111112            );
    112113        }
     
    118119                    'message' => esc_html__( 'API is not properly configured.', 'readmo-ai' ),
    119120                ),
    120                 400
     121                400,
     122                JSON_UNESCAPED_UNICODE
    121123            );
    122124        }
     
    128130                    'message' => esc_html__( 'Source URL is missing.', 'readmo-ai' ),
    129131                ),
    130                 400
     132                400,
     133                JSON_UNESCAPED_UNICODE
    131134            );
    132135        }
     
    143146                    'message' => esc_html__( 'Invalid source URL provided.', 'readmo-ai' ),
    144147                ),
    145                 400
     148                400,
     149                JSON_UNESCAPED_UNICODE
    146150            );
    147151        }
     
    161165                    ),
    162166                ),
    163                 $response['status_code']
     167                $response['status_code'],
     168                JSON_UNESCAPED_UNICODE
    164169            );
    165170        }
     
    171176                    'message' => esc_html__( 'Invalid API response format.', 'readmo-ai' ),
    172177                ),
    173                 500
     178                500,
     179                JSON_UNESCAPED_UNICODE
    174180            );
    175181        }
     
    183189                    'message' => esc_html__( 'Job ID not returned from API.', 'readmo-ai' ),
    184190                ),
    185                 500
     191                500,
     192                JSON_UNESCAPED_UNICODE
    186193            );
    187194        }
     
    192199            array(
    193200                'jobId' => $job_id,
    194             )
     201            ),
     202            null,
     203            JSON_UNESCAPED_UNICODE
    195204        );
    196205    }
     
    212221                    'error_code' => 'nonce_expired',
    213222                ),
    214                 400
     223                400,
     224                JSON_UNESCAPED_UNICODE
    215225            );
    216226        }
     
    222232                    'message' => esc_html__( 'API is not properly configured.', 'readmo-ai' ),
    223233                ),
    224                 400
     234                400,
     235                JSON_UNESCAPED_UNICODE
    225236            );
    226237        }
     
    232243                    'message' => esc_html__( 'Job ID is missing.', 'readmo-ai' ),
    233244                ),
    234                 400
     245                400,
     246                JSON_UNESCAPED_UNICODE
    235247            );
    236248        }
     
    242254                    'message' => esc_html__( 'Job ID is invalid.', 'readmo-ai' ),
    243255                ),
    244                 400
     256                400,
     257                JSON_UNESCAPED_UNICODE
    245258            );
    246259        }
     
    255268                    'message' => $response['error_message'],
    256269                ),
    257                 $response['status_code']
     270                $response['status_code'],
     271                JSON_UNESCAPED_UNICODE
    258272            );
    259273        }
     
    265279                    'message' => esc_html__( 'Invalid API response format.', 'readmo-ai' ),
    266280                ),
    267                 500
     281                500,
     282                JSON_UNESCAPED_UNICODE
    268283            );
    269284        }
     
    281296                'status'    => $status,
    282297                'articleId' => $article_id,
    283             )
     298            ),
     299            null,
     300            JSON_UNESCAPED_UNICODE
    284301        );
    285302    }
     
    301318                    'error_code' => 'nonce_expired',
    302319                ),
    303                 400
     320                400,
     321                JSON_UNESCAPED_UNICODE
    304322            );
    305323        }
     
    311329                    'message' => esc_html__( 'API is not properly configured.', 'readmo-ai' ),
    312330                ),
    313                 400
     331                400,
     332                JSON_UNESCAPED_UNICODE
    314333            );
    315334        }
     
    321340                    'message' => esc_html__( 'Article ID is missing.', 'readmo-ai' ),
    322341                ),
    323                 400
     342                400,
     343                JSON_UNESCAPED_UNICODE
    324344            );
    325345        }
     
    331351                    'message' => esc_html__( 'Article ID is invalid.', 'readmo-ai' ),
    332352                ),
    333                 400
     353                400,
     354                JSON_UNESCAPED_UNICODE
    334355            );
    335356        }
     
    344365                    'message' => $response['error_message'],
    345366                ),
    346                 $response['status_code']
     367                $response['status_code'],
     368                JSON_UNESCAPED_UNICODE
    347369            );
    348370        }
     
    354376                    'message' => esc_html__( 'Invalid API response format.', 'readmo-ai' ),
    355377                ),
    356                 500
     378                500,
     379                JSON_UNESCAPED_UNICODE
    357380            );
    358381        }
     
    361384        $article_data = $response['body'];
    362385
    363         wp_send_json_success( $article_data );
     386        wp_send_json_success( $article_data, null, JSON_UNESCAPED_UNICODE );
    364387    }
    365388
     
    381404                    'error_code' => 'nonce_expired',
    382405                ),
    383                 400
     406                400,
     407                JSON_UNESCAPED_UNICODE
    384408            );
    385409        }
     
    390414                array(
    391415                    'message' => esc_html__( 'API key is not configured. Please configure it in Settings > Readmo AI.', 'readmo-ai' ),
    392                 )
     416                ),
     417                null,
     418                JSON_UNESCAPED_UNICODE
    393419            );
    394420        }
     
    399425        if ( false !== $cached_path_info ) {
    400426            // Return cached data.
    401             wp_send_json_success( $cached_path_info );
     427            wp_send_json_success( $cached_path_info, null, JSON_UNESCAPED_UNICODE );
    402428        }
    403429
     
    410436                array(
    411437                    'message' => $result['error_message'],
    412                 )
     438                ),
     439                null,
     440                JSON_UNESCAPED_UNICODE
    413441            );
    414442        }
     
    443471
    444472        // Return success with path info.
    445         wp_send_json_success( $path_info );
     473        wp_send_json_success( $path_info, null, JSON_UNESCAPED_UNICODE );
    446474    }
    447475
     
    473501            array(
    474502                'nonce' => $new_nonce,
    475             )
     503            ),
     504            null,
     505            JSON_UNESCAPED_UNICODE
    476506        );
    477507    }
  • readmo-ai/tags/1.2.2/Controller/frontend/class-readmo-ai-tracking-handler.php

    r3445269 r3447574  
    8686                    'error_code' => 'nonce_expired',
    8787                ),
    88                 400
     88                400,
     89                JSON_UNESCAPED_UNICODE
    8990            );
    9091            return;
     
    9899                array(
    99100                    'message' => __( 'API Key not configured.', 'readmo-ai' ),
    100                 )
     101                ),
     102                null,
     103                JSON_UNESCAPED_UNICODE
    101104            );
    102105            return;
     
    114117                    array(
    115118                        'message' => __( 'Failed to retrieve client ID.', 'readmo-ai' ),
    116                     )
     119                    ),
     120                    null,
     121                    JSON_UNESCAPED_UNICODE
    117122                );
    118123                return;
     
    148153            array(
    149154                'message' => __( 'Event tracked successfully.', 'readmo-ai' ),
    150             )
     155            ),
     156            null,
     157            JSON_UNESCAPED_UNICODE
    151158        );
    152159    }
  • readmo-ai/tags/1.2.2/Infrastructure/dao/class-readmo-ai-settings-dao.php

    r3447021 r3447574  
    6969        $settings = get_option( self::OPTION_NAME, array() );
    7070
     71        // If no settings exist, initialize with empty defaults in database.
     72        if ( empty( $settings ) ) {
     73            $defaults = array( 'api_key' => '' );
     74            update_option( self::OPTION_NAME, $defaults, true );
     75            return '';
     76        }
     77
    7178        if ( empty( $settings['api_key'] ) ) {
    7279            return '';
     
    118125     */
    119126    public function get_auto_insert_settings() {
    120         // Default: all empty arrays = all checked = apply to all content.
     127        // Default: enabled = true, only 'post' type is checked (page is excluded).
    121128        $defaults = array(
    122             'enabled'              => false,
     129            'enabled'              => true,
    123130            'position'             => 'after_content',
    124             'excluded_post_types'  => array(),
     131            'excluded_post_types'  => array( 'page' ),
    125132            'excluded_categories'  => array(),
    126133            'excluded_posts'       => array(),
     
    129136        $settings = get_option( self::AUTO_INSERT_OPTION_NAME, array() );
    130137
     138        // If no settings exist, initialize with defaults in database.
    131139        if ( empty( $settings ) ) {
     140            update_option( self::AUTO_INSERT_OPTION_NAME, $defaults, true );
    132141            return $defaults;
    133142        }
     
    161170    }
    162171
    163     /**
    164      * Delete auto-insert settings
    165      *
    166      * Removes the auto-insert settings option entirely.
    167      *
    168      * @since 1.2.0
    169      * @return bool True on success, false on failure.
    170      */
    171     public function delete_auto_insert_settings() {
    172         return delete_option( self::AUTO_INSERT_OPTION_NAME );
    173     }
    174172}
  • readmo-ai/tags/1.2.2/View/admin/class-readmo-ai-admin-settings-view.php

    r3447021 r3447574  
    4141        // Using "excluded" storage: empty arrays = all checked (apply to all).
    4242        $ai_enabled             = ! empty( $auto_insert_settings['enabled'] );
    43         $ai_position            = isset( $auto_insert_settings['position'] ) ? $auto_insert_settings['position'] : 'after_content';
    4443        $ai_excluded_post_types = isset( $auto_insert_settings['excluded_post_types'] ) ? $auto_insert_settings['excluded_post_types'] : array();
    4544        $ai_excluded_categories = isset( $auto_insert_settings['excluded_categories'] ) ? $auto_insert_settings['excluded_categories'] : array();
     
    110109                            />
    111110                            <label for="readmo-ai-auto-insert-enabled" class="readmo-ai-toggle-slider"></label>
    112                         </div>
    113                     </div>
    114 
    115                     <!-- Insert Position -->
    116                     <div class="readmo-ai-setting-column">
    117                         <label class="readmo-ai-label">
    118                             <span class="readmo-ai-text"><?php echo esc_html( __( 'Insert Position', 'readmo-ai' ) ); ?></span>
    119                         </label>
    120                         <div class="readmo-ai-radio-group">
    121                             <label class="readmo-ai-radio-label">
    122                                 <input
    123                                     type="radio"
    124                                     name="auto_insert_position"
    125                                     value="after_content"
    126                                     <?php checked( $ai_position, 'after_content' ); ?>
    127                                 />
    128                                 <span class="readmo-ai-radio-dot"></span>
    129                                 <span class="readmo-ai-radio-text"><?php echo esc_html( __( 'After content', 'readmo-ai' ) ); ?></span>
    130                             </label>
    131                             <label class="readmo-ai-radio-label">
    132                                 <input
    133                                     type="radio"
    134                                     name="auto_insert_position"
    135                                     value="footer"
    136                                     <?php checked( $ai_position, 'footer' ); ?>
    137                                 />
    138                                 <span class="readmo-ai-radio-dot"></span>
    139                                 <span class="readmo-ai-radio-text"><?php echo esc_html( __( 'Page footer', 'readmo-ai' ) ); ?></span>
    140                             </label>
    141111                        </div>
    142112                    </div>
     
    255225                </div>
    256226
    257                 <div class="readmo-ai-action readmo-ai-auto-insert-actions">
     227                <div class="readmo-ai-action">
    258228                    <button type="button" id="readmo-ai-save-auto-insert" class="btn btn-ban">
    259229                        <?php echo esc_html( __( 'Save Settings', 'readmo-ai' ) ); ?>
    260230                    </button>
    261                     <button type="button" id="readmo-ai-remove-auto-insert" class="btn btn-danger">
    262                         <?php echo esc_html( __( 'Disable and Remove', 'readmo-ai' ) ); ?>
    263                     </button>
    264                 </div>
    265             </div>
    266 
    267             <!-- Remove Confirmation Modal -->
    268             <div id="readmo-ai-confirm-modal" class="readmo-ai-modal" style="display: none;">
    269                 <div class="readmo-ai-modal-overlay"></div>
    270                 <div class="readmo-ai-modal-content">
    271                     <span class="readmo-ai-title"><?php echo esc_html( __( 'Confirm Remove', 'readmo-ai' ) ); ?></span>
    272                     <span class="readmo-ai-text"><?php echo esc_html( __( 'Are you sure you want to disable and remove all auto-insert settings? This action cannot be undone.', 'readmo-ai' ) ); ?></span>
    273                     <div class="readmo-ai-modal-actions">
    274                         <button type="button" id="readmo-ai-modal-cancel" class="btn btn-tertiary">
    275                             <?php echo esc_html( __( 'Cancel', 'readmo-ai' ) ); ?>
    276                         </button>
    277                         <button type="button" id="readmo-ai-modal-confirm" class="btn btn-danger">
    278                             <?php echo esc_html( __( 'Confirm Remove', 'readmo-ai' ) ); ?>
    279                         </button>
    280                     </div>
    281231                </div>
    282232            </div>
  • readmo-ai/tags/1.2.2/assets/css/admin.css

    r3447021 r3447574  
    1515    align-items: center;
    1616    flex-direction: column;
    17     gap: 12px;
     17    gap: 24px;
     18    padding: 32px 0;
    1819    font-family: Noto Sans TC, PingFang TC, Arial, Helvetica, LiHei Pro, Microsoft JhengHei, MingLiU, sans-serif;
    1920}
     
    5354    display: flex;
    5455    flex-direction: column;
    55     min-width: 720px;
     56    width: 50vw;
     57    max-width: 100%;
    5658    background-color: #ffffff;
    5759    border-radius: 12px;
     
    186188}
    187189
    188 /* Danger Button */
    189 .btn-danger {
    190     background: rgb(235, 67, 67);
    191     color: #ffffff;
    192     border: none;
    193     padding: 16px 20px;
    194 }
    195 
    196 .btn-danger:hover {
    197     background: rgb(220, 38, 38);
    198 }
    199 
    200190/* Ban Button (Disabled State) */
    201191.btn-ban,
     
    434424.readmo-ai-content-tree {
    435425    max-height: 400px;
     426    max-width: 100%;
    436427    overflow: auto;
    437428    padding: 12px;
     
    491482    cursor: pointer;
    492483    flex: 1;
     484    min-width: 0;
     485    overflow: hidden;
    493486}
    494487
     
    555548    color: var(--Text-Neutral-400, rgba(74, 75, 88, 1));
    556549    transition: color 0.15s ease;
     550    overflow: hidden;
     551    text-overflow: ellipsis;
     552    white-space: nowrap;
    557553}
    558554
     
    588584}
    589585
    590 /* Auto-Insert Actions */
    591 .readmo-ai-auto-insert-actions {
    592     justify-content: space-between;
    593 }
    594 
    595 /* Modal Styles */
    596 .readmo-ai-modal {
    597     position: fixed;
    598     top: 0;
    599     left: 0;
    600     width: 100%;
    601     height: 100%;
    602     z-index: 100000;
    603     display: flex;
    604     align-items: center;
    605     justify-content: center;
    606 }
    607 
    608 .readmo-ai-modal-overlay {
    609     position: absolute;
    610     top: 0;
    611     left: 0;
    612     width: 100%;
    613     height: 100%;
    614     background: rgba(0, 0, 0, 0.5);
    615 }
    616 
    617 .readmo-ai-modal-content {
    618     display: flex;
    619     flex-direction: column;
    620     gap: 24px;
    621     position: relative;
    622     background: #ffffff;
    623     padding: 24px;
    624     border-radius: 12px;
    625     max-width: 400px;
    626     width: 90%;
    627     box-shadow: 0 4px 20px rgba(0, 0, 0, 0.15);
    628 }
    629 
    630 .readmo-ai-modal-content h3 {
    631     font-size: 18px;
    632     font-weight: 600;
    633     color: var(--Text-Neutral-400, rgba(74, 75, 88, 1));
    634 }
    635 
    636 .readmo-ai-modal-content p {
    637     font-size: 14px;
    638     color: var(--Text-Neutral-300, rgba(113, 113, 113, 1));
    639     line-height: 1.5;
    640 }
    641 
    642 .readmo-ai-modal-actions {
    643     display: flex;
    644     justify-content: flex-end;
    645     gap: 12px;
    646 }
    647 
    648 .readmo-ai-modal-actions .btn {
    649     width: auto;
    650     padding: 10px 20px;
    651 }
    652 
    653586@media screen and (max-width: 767px) {
    654587    .readmo-ai-settings-container {
     
    679612    }
    680613
    681     .btn-danger {
    682         width: auto;
    683         padding: 12px 16px;
    684     }
    685 
    686     .readmo-ai-auto-insert-actions {
    687         flex-direction: column;
    688         gap: 12px;
    689     }
    690 
    691     .readmo-ai-auto-insert-actions .btn {
    692         width: 100%;
    693     }
    694 
    695614    .readmo-ai-checkbox-group,
    696615    .readmo-ai-radio-group {
  • readmo-ai/tags/1.2.2/assets/css/frontend.css

    r3411004 r3447574  
    3535
    3636.readmo-ai-question-icon {
    37     width: 28px;
    38     height: 28px;
     37    width: 24px;
     38    height: 24px;
    3939    flex-shrink: 0;
    4040}
     
    4242.readmo-ai-question-title {
    4343    font-weight: 600;
    44     font-size: 24px;
     44    font-size: 20px;
    4545    color: #215376;
    46     line-height: 28px;
     46    line-height: 24px;
    4747}
    4848
     
    5050.readmo-ai-questions {
    5151    display: flex;
    52     flex-wrap: wrap;
     52    flex-direction: column;
     53    align-items: flex-start;
    5354    gap: 12px;
    5455    margin: 0;
     
    5960/* Question Button Styles */
    6061.readmo-ai-question-btn {
     62    display: inline-flex;
    6163    position: relative;
    6264    border-radius: 12px;
    63     padding: 1rem;
     65    padding: 12px 16px;
    6466    background-color: #ffffff;
    6567    box-shadow: 0px 2px 4px 0px rgba(62, 179, 218, 0.2);
     
    107109    font-weight: 400;
    108110    color: #26272C;
    109     font-size: 20px;
    110     line-height: 24px;
     111    font-size: 16px;
     112    line-height: 20px;
    111113    transition: 0.3s ease-out;
     114    text-decoration: none;
    112115}
    113116
     
    123126@media screen and (max-width: 767px) {
    124127    .readmo-ai-question-title {
    125         font-size: 20px;
    126         line-height: 24px;
     128        font-size: 16px;
     129        line-height: 20px;
    127130    }
    128131
    129132    .readmo-ai-question-btn {
    130         font-size: 16px;
    131         line-height: 20px;
    132         padding: 10px 14px;
     133        font-size: 12px;
     134        line-height: 16px;
     135        padding: 8px 12px;
    133136    }
    134137}
  • readmo-ai/tags/1.2.2/assets/js/admin.js

    r3447021 r3447574  
    256256        cacheElements: function () {
    257257            this.$enabledCheckbox = $( '#readmo-ai-auto-insert-enabled' );
    258             this.$positionRadios  = $( 'input[name="auto_insert_position"]' );
    259258            this.$fromUrlInput    = $( '#readmo-ai-from-url' );
    260259            this.$contentTree     = $( '#readmo-ai-content-tree' );
    261260            this.$saveButton      = $( '#readmo-ai-save-auto-insert' );
    262             this.$removeButton    = $( '#readmo-ai-remove-auto-insert' );
    263             this.$modal           = $( '#readmo-ai-confirm-modal' );
    264             this.$modalCancel     = $( '#readmo-ai-modal-cancel' );
    265             this.$modalConfirm    = $( '#readmo-ai-modal-confirm' );
    266             this.$modalOverlay    = $( '.readmo-ai-modal-overlay' );
    267261        },
    268262
     
    321315            return {
    322316                enabled: this.$enabledCheckbox.is( ':checked' ),
    323                 position: $( 'input[name="auto_insert_position"]:checked' ).val(),
    324317                fromUrl: this.$fromUrlInput.val(),
    325318                excludedPostTypes: excludedPostTypes,
     
    367360            });
    368361
    369             this.$positionRadios.on( 'change', function () {
    370                 self.updateSaveButtonState();
    371             });
    372 
    373362            this.$fromUrlInput.on( 'input', function () {
    374363                self.updateSaveButtonState();
     
    402391                e.preventDefault();
    403392                self.saveSettings();
    404             });
    405 
    406             // Remove button click.
    407             this.$removeButton.on( 'click', function ( e ) {
    408                 e.preventDefault();
    409                 self.showModal();
    410             });
    411 
    412             // Modal cancel.
    413             this.$modalCancel.on( 'click', function ( e ) {
    414                 e.preventDefault();
    415                 self.hideModal();
    416             });
    417 
    418             // Modal overlay click.
    419             this.$modalOverlay.on( 'click', function () {
    420                 self.hideModal();
    421             });
    422 
    423             // Modal confirm.
    424             this.$modalConfirm.on( 'click', function ( e ) {
    425                 e.preventDefault();
    426                 self.removeSettings();
    427             });
    428 
    429             // ESC key to close modal.
    430             $( document ).on( 'keydown', function ( e ) {
    431                 if ( e.key === 'Escape' && self.$modal.is( ':visible' ) ) {
    432                     self.hideModal();
    433                 }
    434393            });
    435394        },
     
    582541                    nonce: readmoAiAdminData.nonce,
    583542                    enabled: values.enabled ? 1 : 0,
    584                     position: values.position,
    585543                    from_url: values.fromUrl,
    586544                    excluded_post_types: values.excludedPostTypes,
     
    624582                }
    625583            });
    626         },
    627 
    628         /**
    629          * Show confirmation modal.
    630          */
    631         showModal: function () {
    632             this.$modal.fadeIn( 200 );
    633         },
    634 
    635         /**
    636          * Hide confirmation modal.
    637          */
    638         hideModal: function () {
    639             this.$modal.fadeOut( 200 );
    640         },
    641 
    642         /**
    643          * Remove auto-insert settings via AJAX.
    644          */
    645         removeSettings: function () {
    646             var self = this;
    647 
    648             // Disable confirm button.
    649             this.$modalConfirm.prop( 'disabled', true ).text( readmoAiAdminData.i18n.saving );
    650 
    651             $.ajax({
    652                 type: 'POST',
    653                 url: readmoAiAdminData.ajaxUrl,
    654                 data: {
    655                     action: 'readmo_ai_delete_auto_insert_settings',
    656                     nonce: readmoAiAdminData.nonce
    657                 },
    658                 success: function ( response ) {
    659                     if ( response.success ) {
    660                         // Reset form to defaults (all checked).
    661                         self.$enabledCheckbox.prop( 'checked', false );
    662                         $( 'input[name="auto_insert_position"][value="after_content"]' ).prop( 'checked', true );
    663                         self.$fromUrlInput.val( '' );
    664 
    665                         // Check all tree items.
    666                         self.$contentTree.find( '.readmo-ai-tree-input' ).prop( 'checked', true ).prop( 'indeterminate', false );
    667                         self.$contentTree.find( '.readmo-ai-tree-node' ).removeClass( 'unchecked' );
    668 
    669                         // Update original values.
    670                         self.originalValues = self.getFormValues();
    671 
    672                         // Reset button state.
    673                         self.$saveButton
    674                             .removeClass( 'btn-secondary' )
    675                             .addClass( 'btn-ban' )
    676                             .prop( 'disabled', true );
    677 
    678                         // Hide modal.
    679                         self.hideModal();
    680 
    681                         // Re-enable confirm button.
    682                         self.$modalConfirm.prop( 'disabled', false ).text( readmoAiAdminData.i18n.confirmRemove || 'Confirm Remove' );
    683 
    684                         // Show success message.
    685                         ReadmoAiAdmin.showNotice( 'success', response.data.message );
    686                     } else {
    687                         // Show error message.
    688                         ReadmoAiAdmin.showNotice( 'error', response.data.message );
    689 
    690                         // Hide modal.
    691                         self.hideModal();
    692 
    693                         // Re-enable confirm button.
    694                         self.$modalConfirm.prop( 'disabled', false ).text( readmoAiAdminData.i18n.confirmRemove || 'Confirm Remove' );
    695                     }
    696                 },
    697                 error: function () {
    698                     // Show error message.
    699                     ReadmoAiAdmin.showNotice( 'error', 'An error occurred while removing settings.' );
    700 
    701                     // Hide modal.
    702                     self.hideModal();
    703 
    704                     // Re-enable confirm button.
    705                     self.$modalConfirm.prop( 'disabled', false ).text( readmoAiAdminData.i18n.confirmRemove || 'Confirm Remove' );
    706                 }
    707             });
    708584        }
    709585    };
  • readmo-ai/tags/1.2.2/assets/svg/question.svg

    r3411004 r3447574  
    1 <svg width="28" height="28" viewBox="0 0 64 64" fill="none" xmlns="http://www.w3.org/2000/svg">
     1<svg width="24" height="24" viewBox="0 0 64 64" fill="none" xmlns="http://www.w3.org/2000/svg">
    22<g clip-path="url(#clip0_2581_15276)">
    33<path d="M43.4926 22.9982C43.5179 19.3262 42.5599 15.7144 40.7181 12.5377C38.8762 9.36101 36.2177 6.73523 33.0184 4.93294C29.819 3.13066 26.1956 2.21758 22.5243 2.28851C18.853 2.35943 15.2675 3.41177 12.1402 5.33628C9.01287 7.26076 6.45767 9.9873 4.73991 13.2327C3.02212 16.4782 2.20436 20.1243 2.37152 23.7926C2.53867 27.4608 3.68466 31.0174 5.69049 34.0932C7.6963 37.169 10.4889 39.6518 13.7783 41.2839V48.1411C13.7783 48.7473 14.0191 49.3288 14.4478 49.7571C14.8764 50.1859 15.4578 50.4268 16.064 50.4268H29.7783C30.3845 50.4268 30.9659 50.1859 31.3945 49.7571C31.8232 49.3288 32.064 48.7473 32.064 48.1411V41.2839C35.481 39.6003 38.3608 36.9972 40.3797 33.767C42.3987 30.5367 43.4766 26.8074 43.4926 22.9982Z" fill="url(#paint0_radial_2581_15276)"/>
  • readmo-ai/tags/1.2.2/readme.txt

    r3447213 r3447574  
    55Tested up to: 6.9
    66Requires PHP: 7.4
    7 Stable tag: 1.2.1
     7Stable tag: 1.2.2
    88License: GPLv2 or later
    99License URI: https://www.gnu.org/licenses/gpl-2.0.html
  • readmo-ai/tags/1.2.2/readmo-ai.php

    r3447213 r3447574  
    1313 * Plugin Name:       Readmo AI
    1414 * Description:       AI-powered content analysis and optimization for WordPress with analytics tracking
    15  * Version:           1.2.1
     15 * Version:           1.2.2
    1616 * Requires at least: 5.9
    1717 * Requires PHP:      7.4
     
    3333 */
    3434if ( ! defined( 'READMO_AI_VERSION' ) ) {
    35     define( 'READMO_AI_VERSION', '1.2.1' );
     35    define( 'READMO_AI_VERSION', '1.2.2' );
    3636}
    3737
  • readmo-ai/trunk/Controller/admin/class-readmo-ai-admin-settings.php

    r3447021 r3447574  
    112112        add_action( 'wp_ajax_readmo_ai_save_settings', array( $this, 'ajax_save_settings' ) );
    113113        add_action( 'wp_ajax_readmo_ai_save_auto_insert_settings', array( $this, 'ajax_save_auto_insert_settings' ) );
    114         add_action( 'wp_ajax_readmo_ai_delete_auto_insert_settings', array( $this, 'ajax_delete_auto_insert_settings' ) );
    115114    }
    116115
     
    343342                array(
    344343                    'message' => __( 'Security check failed', 'readmo-ai' ),
    345                 )
     344                ),
     345                null,
     346                JSON_UNESCAPED_UNICODE
    346347            );
    347348        }
     
    352353                array(
    353354                    'message' => __( 'Insufficient permissions', 'readmo-ai' ),
    354                 )
     355                ),
     356                null,
     357                JSON_UNESCAPED_UNICODE
    355358            );
    356359        }
     
    361364                array(
    362365                    'message' => __( 'API Key is required', 'readmo-ai' ),
    363                 )
     366                ),
     367                null,
     368                JSON_UNESCAPED_UNICODE
    364369            );
    365370        }
     
    372377                array(
    373378                    'message' => __( 'API Key cannot be empty', 'readmo-ai' ),
    374                 )
     379                ),
     380                null,
     381                JSON_UNESCAPED_UNICODE
    375382            );
    376383        }
     
    387394                array(
    388395                    'message' => __( 'Settings saved successfully', 'readmo-ai' ),
    389                 )
     396                ),
     397                null,
     398                JSON_UNESCAPED_UNICODE
    390399            );
    391400        } else {
     
    393402                array(
    394403                    'message' => __( 'Failed to save settings', 'readmo-ai' ),
    395                 )
     404                ),
     405                null,
     406                JSON_UNESCAPED_UNICODE
    396407            );
    397408        }
     
    412423                array(
    413424                    'message' => __( 'Security check failed', 'readmo-ai' ),
    414                 )
     425                ),
     426                null,
     427                JSON_UNESCAPED_UNICODE
    415428            );
    416429        }
     
    421434                array(
    422435                    'message' => __( 'Insufficient permissions', 'readmo-ai' ),
    423                 )
     436                ),
     437                null,
     438                JSON_UNESCAPED_UNICODE
    424439            );
    425440        }
     
    437452            wp_send_json_success(
    438453                array(
    439                     'message'          => __( 'Auto-insert settings saved successfully', 'readmo-ai' ),
    440                     'saved_settings'   => $auto_insert_settings,
     454                    'message'           => __( 'Auto-insert settings saved successfully', 'readmo-ai' ),
     455                    'saved_settings'    => $auto_insert_settings,
    441456                    'verified_settings' => $verified_settings,
    442                 )
     457                ),
     458                null,
     459                JSON_UNESCAPED_UNICODE
    443460            );
    444461        } else {
    445462            wp_send_json_error(
    446463                array(
    447                     'message'          => __( 'Failed to save auto-insert settings', 'readmo-ai' ),
     464                    'message'            => __( 'Failed to save auto-insert settings', 'readmo-ai' ),
    448465                    'attempted_settings' => $auto_insert_settings,
    449                 )
    450             );
    451         }
    452     }
    453 
    454     /**
    455      * AJAX handler to delete auto-insert settings
    456      *
    457      * Handles AJAX requests to remove auto-insert configuration.
    458      *
    459      * @since 1.2.0
    460      * @return void
    461      */
    462     public function ajax_delete_auto_insert_settings() {
    463         // Verify nonce.
    464         if ( ! isset( $_POST['nonce'] ) || ! wp_verify_nonce( sanitize_text_field( wp_unslash( $_POST['nonce'] ) ), 'readmo_ai_admin_nonce' ) ) {
    465             wp_send_json_error(
    466                 array(
    467                     'message' => __( 'Security check failed', 'readmo-ai' ),
    468                 )
    469             );
    470         }
    471 
    472         // Check user capabilities.
    473         if ( ! current_user_can( 'manage_options' ) ) {
    474             wp_send_json_error(
    475                 array(
    476                     'message' => __( 'Insufficient permissions', 'readmo-ai' ),
    477                 )
    478             );
    479         }
    480 
    481         // Delete settings.
    482         $deleted = $this->settings_dao->delete_auto_insert_settings();
    483 
    484         if ( $deleted ) {
    485             wp_send_json_success(
    486                 array(
    487                     'message' => __( 'Auto-insert settings removed successfully', 'readmo-ai' ),
    488                 )
    489             );
    490         } else {
    491             wp_send_json_error(
    492                 array(
    493                     'message' => __( 'Failed to remove auto-insert settings', 'readmo-ai' ),
    494                 )
     466                ),
     467                null,
     468                JSON_UNESCAPED_UNICODE
    495469            );
    496470        }
     
    513487        $settings['enabled'] = ! empty( $post_data['enabled'] );
    514488
    515         // Position.
    516         $allowed_positions    = array( 'before_content', 'after_content', 'footer' );
     489        // Position is fixed to 'after_content'.
    517490        $settings['position'] = 'after_content';
    518         if ( isset( $post_data['position'] ) && in_array( $post_data['position'], $allowed_positions, true ) ) {
    519             $settings['position'] = sanitize_text_field( $post_data['position'] );
    520         }
    521491
    522492        // Excluded post types (array of post type names).
  • readmo-ai/trunk/Controller/frontend/class-readmo-ai-ajax-handler.php

    r3445269 r3447574  
    108108                    'error_code' => 'nonce_expired',
    109109                ),
    110                 400
     110                400,
     111                JSON_UNESCAPED_UNICODE
    111112            );
    112113        }
     
    118119                    'message' => esc_html__( 'API is not properly configured.', 'readmo-ai' ),
    119120                ),
    120                 400
     121                400,
     122                JSON_UNESCAPED_UNICODE
    121123            );
    122124        }
     
    128130                    'message' => esc_html__( 'Source URL is missing.', 'readmo-ai' ),
    129131                ),
    130                 400
     132                400,
     133                JSON_UNESCAPED_UNICODE
    131134            );
    132135        }
     
    143146                    'message' => esc_html__( 'Invalid source URL provided.', 'readmo-ai' ),
    144147                ),
    145                 400
     148                400,
     149                JSON_UNESCAPED_UNICODE
    146150            );
    147151        }
     
    161165                    ),
    162166                ),
    163                 $response['status_code']
     167                $response['status_code'],
     168                JSON_UNESCAPED_UNICODE
    164169            );
    165170        }
     
    171176                    'message' => esc_html__( 'Invalid API response format.', 'readmo-ai' ),
    172177                ),
    173                 500
     178                500,
     179                JSON_UNESCAPED_UNICODE
    174180            );
    175181        }
     
    183189                    'message' => esc_html__( 'Job ID not returned from API.', 'readmo-ai' ),
    184190                ),
    185                 500
     191                500,
     192                JSON_UNESCAPED_UNICODE
    186193            );
    187194        }
     
    192199            array(
    193200                'jobId' => $job_id,
    194             )
     201            ),
     202            null,
     203            JSON_UNESCAPED_UNICODE
    195204        );
    196205    }
     
    212221                    'error_code' => 'nonce_expired',
    213222                ),
    214                 400
     223                400,
     224                JSON_UNESCAPED_UNICODE
    215225            );
    216226        }
     
    222232                    'message' => esc_html__( 'API is not properly configured.', 'readmo-ai' ),
    223233                ),
    224                 400
     234                400,
     235                JSON_UNESCAPED_UNICODE
    225236            );
    226237        }
     
    232243                    'message' => esc_html__( 'Job ID is missing.', 'readmo-ai' ),
    233244                ),
    234                 400
     245                400,
     246                JSON_UNESCAPED_UNICODE
    235247            );
    236248        }
     
    242254                    'message' => esc_html__( 'Job ID is invalid.', 'readmo-ai' ),
    243255                ),
    244                 400
     256                400,
     257                JSON_UNESCAPED_UNICODE
    245258            );
    246259        }
     
    255268                    'message' => $response['error_message'],
    256269                ),
    257                 $response['status_code']
     270                $response['status_code'],
     271                JSON_UNESCAPED_UNICODE
    258272            );
    259273        }
     
    265279                    'message' => esc_html__( 'Invalid API response format.', 'readmo-ai' ),
    266280                ),
    267                 500
     281                500,
     282                JSON_UNESCAPED_UNICODE
    268283            );
    269284        }
     
    281296                'status'    => $status,
    282297                'articleId' => $article_id,
    283             )
     298            ),
     299            null,
     300            JSON_UNESCAPED_UNICODE
    284301        );
    285302    }
     
    301318                    'error_code' => 'nonce_expired',
    302319                ),
    303                 400
     320                400,
     321                JSON_UNESCAPED_UNICODE
    304322            );
    305323        }
     
    311329                    'message' => esc_html__( 'API is not properly configured.', 'readmo-ai' ),
    312330                ),
    313                 400
     331                400,
     332                JSON_UNESCAPED_UNICODE
    314333            );
    315334        }
     
    321340                    'message' => esc_html__( 'Article ID is missing.', 'readmo-ai' ),
    322341                ),
    323                 400
     342                400,
     343                JSON_UNESCAPED_UNICODE
    324344            );
    325345        }
     
    331351                    'message' => esc_html__( 'Article ID is invalid.', 'readmo-ai' ),
    332352                ),
    333                 400
     353                400,
     354                JSON_UNESCAPED_UNICODE
    334355            );
    335356        }
     
    344365                    'message' => $response['error_message'],
    345366                ),
    346                 $response['status_code']
     367                $response['status_code'],
     368                JSON_UNESCAPED_UNICODE
    347369            );
    348370        }
     
    354376                    'message' => esc_html__( 'Invalid API response format.', 'readmo-ai' ),
    355377                ),
    356                 500
     378                500,
     379                JSON_UNESCAPED_UNICODE
    357380            );
    358381        }
     
    361384        $article_data = $response['body'];
    362385
    363         wp_send_json_success( $article_data );
     386        wp_send_json_success( $article_data, null, JSON_UNESCAPED_UNICODE );
    364387    }
    365388
     
    381404                    'error_code' => 'nonce_expired',
    382405                ),
    383                 400
     406                400,
     407                JSON_UNESCAPED_UNICODE
    384408            );
    385409        }
     
    390414                array(
    391415                    'message' => esc_html__( 'API key is not configured. Please configure it in Settings > Readmo AI.', 'readmo-ai' ),
    392                 )
     416                ),
     417                null,
     418                JSON_UNESCAPED_UNICODE
    393419            );
    394420        }
     
    399425        if ( false !== $cached_path_info ) {
    400426            // Return cached data.
    401             wp_send_json_success( $cached_path_info );
     427            wp_send_json_success( $cached_path_info, null, JSON_UNESCAPED_UNICODE );
    402428        }
    403429
     
    410436                array(
    411437                    'message' => $result['error_message'],
    412                 )
     438                ),
     439                null,
     440                JSON_UNESCAPED_UNICODE
    413441            );
    414442        }
     
    443471
    444472        // Return success with path info.
    445         wp_send_json_success( $path_info );
     473        wp_send_json_success( $path_info, null, JSON_UNESCAPED_UNICODE );
    446474    }
    447475
     
    473501            array(
    474502                'nonce' => $new_nonce,
    475             )
     503            ),
     504            null,
     505            JSON_UNESCAPED_UNICODE
    476506        );
    477507    }
  • readmo-ai/trunk/Controller/frontend/class-readmo-ai-tracking-handler.php

    r3445269 r3447574  
    8686                    'error_code' => 'nonce_expired',
    8787                ),
    88                 400
     88                400,
     89                JSON_UNESCAPED_UNICODE
    8990            );
    9091            return;
     
    9899                array(
    99100                    'message' => __( 'API Key not configured.', 'readmo-ai' ),
    100                 )
     101                ),
     102                null,
     103                JSON_UNESCAPED_UNICODE
    101104            );
    102105            return;
     
    114117                    array(
    115118                        'message' => __( 'Failed to retrieve client ID.', 'readmo-ai' ),
    116                     )
     119                    ),
     120                    null,
     121                    JSON_UNESCAPED_UNICODE
    117122                );
    118123                return;
     
    148153            array(
    149154                'message' => __( 'Event tracked successfully.', 'readmo-ai' ),
    150             )
     155            ),
     156            null,
     157            JSON_UNESCAPED_UNICODE
    151158        );
    152159    }
  • readmo-ai/trunk/Infrastructure/dao/class-readmo-ai-settings-dao.php

    r3447021 r3447574  
    6969        $settings = get_option( self::OPTION_NAME, array() );
    7070
     71        // If no settings exist, initialize with empty defaults in database.
     72        if ( empty( $settings ) ) {
     73            $defaults = array( 'api_key' => '' );
     74            update_option( self::OPTION_NAME, $defaults, true );
     75            return '';
     76        }
     77
    7178        if ( empty( $settings['api_key'] ) ) {
    7279            return '';
     
    118125     */
    119126    public function get_auto_insert_settings() {
    120         // Default: all empty arrays = all checked = apply to all content.
     127        // Default: enabled = true, only 'post' type is checked (page is excluded).
    121128        $defaults = array(
    122             'enabled'              => false,
     129            'enabled'              => true,
    123130            'position'             => 'after_content',
    124             'excluded_post_types'  => array(),
     131            'excluded_post_types'  => array( 'page' ),
    125132            'excluded_categories'  => array(),
    126133            'excluded_posts'       => array(),
     
    129136        $settings = get_option( self::AUTO_INSERT_OPTION_NAME, array() );
    130137
     138        // If no settings exist, initialize with defaults in database.
    131139        if ( empty( $settings ) ) {
     140            update_option( self::AUTO_INSERT_OPTION_NAME, $defaults, true );
    132141            return $defaults;
    133142        }
     
    161170    }
    162171
    163     /**
    164      * Delete auto-insert settings
    165      *
    166      * Removes the auto-insert settings option entirely.
    167      *
    168      * @since 1.2.0
    169      * @return bool True on success, false on failure.
    170      */
    171     public function delete_auto_insert_settings() {
    172         return delete_option( self::AUTO_INSERT_OPTION_NAME );
    173     }
    174172}
  • readmo-ai/trunk/View/admin/class-readmo-ai-admin-settings-view.php

    r3447021 r3447574  
    4141        // Using "excluded" storage: empty arrays = all checked (apply to all).
    4242        $ai_enabled             = ! empty( $auto_insert_settings['enabled'] );
    43         $ai_position            = isset( $auto_insert_settings['position'] ) ? $auto_insert_settings['position'] : 'after_content';
    4443        $ai_excluded_post_types = isset( $auto_insert_settings['excluded_post_types'] ) ? $auto_insert_settings['excluded_post_types'] : array();
    4544        $ai_excluded_categories = isset( $auto_insert_settings['excluded_categories'] ) ? $auto_insert_settings['excluded_categories'] : array();
     
    110109                            />
    111110                            <label for="readmo-ai-auto-insert-enabled" class="readmo-ai-toggle-slider"></label>
    112                         </div>
    113                     </div>
    114 
    115                     <!-- Insert Position -->
    116                     <div class="readmo-ai-setting-column">
    117                         <label class="readmo-ai-label">
    118                             <span class="readmo-ai-text"><?php echo esc_html( __( 'Insert Position', 'readmo-ai' ) ); ?></span>
    119                         </label>
    120                         <div class="readmo-ai-radio-group">
    121                             <label class="readmo-ai-radio-label">
    122                                 <input
    123                                     type="radio"
    124                                     name="auto_insert_position"
    125                                     value="after_content"
    126                                     <?php checked( $ai_position, 'after_content' ); ?>
    127                                 />
    128                                 <span class="readmo-ai-radio-dot"></span>
    129                                 <span class="readmo-ai-radio-text"><?php echo esc_html( __( 'After content', 'readmo-ai' ) ); ?></span>
    130                             </label>
    131                             <label class="readmo-ai-radio-label">
    132                                 <input
    133                                     type="radio"
    134                                     name="auto_insert_position"
    135                                     value="footer"
    136                                     <?php checked( $ai_position, 'footer' ); ?>
    137                                 />
    138                                 <span class="readmo-ai-radio-dot"></span>
    139                                 <span class="readmo-ai-radio-text"><?php echo esc_html( __( 'Page footer', 'readmo-ai' ) ); ?></span>
    140                             </label>
    141111                        </div>
    142112                    </div>
     
    255225                </div>
    256226
    257                 <div class="readmo-ai-action readmo-ai-auto-insert-actions">
     227                <div class="readmo-ai-action">
    258228                    <button type="button" id="readmo-ai-save-auto-insert" class="btn btn-ban">
    259229                        <?php echo esc_html( __( 'Save Settings', 'readmo-ai' ) ); ?>
    260230                    </button>
    261                     <button type="button" id="readmo-ai-remove-auto-insert" class="btn btn-danger">
    262                         <?php echo esc_html( __( 'Disable and Remove', 'readmo-ai' ) ); ?>
    263                     </button>
    264                 </div>
    265             </div>
    266 
    267             <!-- Remove Confirmation Modal -->
    268             <div id="readmo-ai-confirm-modal" class="readmo-ai-modal" style="display: none;">
    269                 <div class="readmo-ai-modal-overlay"></div>
    270                 <div class="readmo-ai-modal-content">
    271                     <span class="readmo-ai-title"><?php echo esc_html( __( 'Confirm Remove', 'readmo-ai' ) ); ?></span>
    272                     <span class="readmo-ai-text"><?php echo esc_html( __( 'Are you sure you want to disable and remove all auto-insert settings? This action cannot be undone.', 'readmo-ai' ) ); ?></span>
    273                     <div class="readmo-ai-modal-actions">
    274                         <button type="button" id="readmo-ai-modal-cancel" class="btn btn-tertiary">
    275                             <?php echo esc_html( __( 'Cancel', 'readmo-ai' ) ); ?>
    276                         </button>
    277                         <button type="button" id="readmo-ai-modal-confirm" class="btn btn-danger">
    278                             <?php echo esc_html( __( 'Confirm Remove', 'readmo-ai' ) ); ?>
    279                         </button>
    280                     </div>
    281231                </div>
    282232            </div>
  • readmo-ai/trunk/assets/css/admin.css

    r3447021 r3447574  
    1515    align-items: center;
    1616    flex-direction: column;
    17     gap: 12px;
     17    gap: 24px;
     18    padding: 32px 0;
    1819    font-family: Noto Sans TC, PingFang TC, Arial, Helvetica, LiHei Pro, Microsoft JhengHei, MingLiU, sans-serif;
    1920}
     
    5354    display: flex;
    5455    flex-direction: column;
    55     min-width: 720px;
     56    width: 50vw;
     57    max-width: 100%;
    5658    background-color: #ffffff;
    5759    border-radius: 12px;
     
    186188}
    187189
    188 /* Danger Button */
    189 .btn-danger {
    190     background: rgb(235, 67, 67);
    191     color: #ffffff;
    192     border: none;
    193     padding: 16px 20px;
    194 }
    195 
    196 .btn-danger:hover {
    197     background: rgb(220, 38, 38);
    198 }
    199 
    200190/* Ban Button (Disabled State) */
    201191.btn-ban,
     
    434424.readmo-ai-content-tree {
    435425    max-height: 400px;
     426    max-width: 100%;
    436427    overflow: auto;
    437428    padding: 12px;
     
    491482    cursor: pointer;
    492483    flex: 1;
     484    min-width: 0;
     485    overflow: hidden;
    493486}
    494487
     
    555548    color: var(--Text-Neutral-400, rgba(74, 75, 88, 1));
    556549    transition: color 0.15s ease;
     550    overflow: hidden;
     551    text-overflow: ellipsis;
     552    white-space: nowrap;
    557553}
    558554
     
    588584}
    589585
    590 /* Auto-Insert Actions */
    591 .readmo-ai-auto-insert-actions {
    592     justify-content: space-between;
    593 }
    594 
    595 /* Modal Styles */
    596 .readmo-ai-modal {
    597     position: fixed;
    598     top: 0;
    599     left: 0;
    600     width: 100%;
    601     height: 100%;
    602     z-index: 100000;
    603     display: flex;
    604     align-items: center;
    605     justify-content: center;
    606 }
    607 
    608 .readmo-ai-modal-overlay {
    609     position: absolute;
    610     top: 0;
    611     left: 0;
    612     width: 100%;
    613     height: 100%;
    614     background: rgba(0, 0, 0, 0.5);
    615 }
    616 
    617 .readmo-ai-modal-content {
    618     display: flex;
    619     flex-direction: column;
    620     gap: 24px;
    621     position: relative;
    622     background: #ffffff;
    623     padding: 24px;
    624     border-radius: 12px;
    625     max-width: 400px;
    626     width: 90%;
    627     box-shadow: 0 4px 20px rgba(0, 0, 0, 0.15);
    628 }
    629 
    630 .readmo-ai-modal-content h3 {
    631     font-size: 18px;
    632     font-weight: 600;
    633     color: var(--Text-Neutral-400, rgba(74, 75, 88, 1));
    634 }
    635 
    636 .readmo-ai-modal-content p {
    637     font-size: 14px;
    638     color: var(--Text-Neutral-300, rgba(113, 113, 113, 1));
    639     line-height: 1.5;
    640 }
    641 
    642 .readmo-ai-modal-actions {
    643     display: flex;
    644     justify-content: flex-end;
    645     gap: 12px;
    646 }
    647 
    648 .readmo-ai-modal-actions .btn {
    649     width: auto;
    650     padding: 10px 20px;
    651 }
    652 
    653586@media screen and (max-width: 767px) {
    654587    .readmo-ai-settings-container {
     
    679612    }
    680613
    681     .btn-danger {
    682         width: auto;
    683         padding: 12px 16px;
    684     }
    685 
    686     .readmo-ai-auto-insert-actions {
    687         flex-direction: column;
    688         gap: 12px;
    689     }
    690 
    691     .readmo-ai-auto-insert-actions .btn {
    692         width: 100%;
    693     }
    694 
    695614    .readmo-ai-checkbox-group,
    696615    .readmo-ai-radio-group {
  • readmo-ai/trunk/assets/css/frontend.css

    r3411004 r3447574  
    3535
    3636.readmo-ai-question-icon {
    37     width: 28px;
    38     height: 28px;
     37    width: 24px;
     38    height: 24px;
    3939    flex-shrink: 0;
    4040}
     
    4242.readmo-ai-question-title {
    4343    font-weight: 600;
    44     font-size: 24px;
     44    font-size: 20px;
    4545    color: #215376;
    46     line-height: 28px;
     46    line-height: 24px;
    4747}
    4848
     
    5050.readmo-ai-questions {
    5151    display: flex;
    52     flex-wrap: wrap;
     52    flex-direction: column;
     53    align-items: flex-start;
    5354    gap: 12px;
    5455    margin: 0;
     
    5960/* Question Button Styles */
    6061.readmo-ai-question-btn {
     62    display: inline-flex;
    6163    position: relative;
    6264    border-radius: 12px;
    63     padding: 1rem;
     65    padding: 12px 16px;
    6466    background-color: #ffffff;
    6567    box-shadow: 0px 2px 4px 0px rgba(62, 179, 218, 0.2);
     
    107109    font-weight: 400;
    108110    color: #26272C;
    109     font-size: 20px;
    110     line-height: 24px;
     111    font-size: 16px;
     112    line-height: 20px;
    111113    transition: 0.3s ease-out;
     114    text-decoration: none;
    112115}
    113116
     
    123126@media screen and (max-width: 767px) {
    124127    .readmo-ai-question-title {
    125         font-size: 20px;
    126         line-height: 24px;
     128        font-size: 16px;
     129        line-height: 20px;
    127130    }
    128131
    129132    .readmo-ai-question-btn {
    130         font-size: 16px;
    131         line-height: 20px;
    132         padding: 10px 14px;
     133        font-size: 12px;
     134        line-height: 16px;
     135        padding: 8px 12px;
    133136    }
    134137}
  • readmo-ai/trunk/assets/js/admin.js

    r3447021 r3447574  
    256256        cacheElements: function () {
    257257            this.$enabledCheckbox = $( '#readmo-ai-auto-insert-enabled' );
    258             this.$positionRadios  = $( 'input[name="auto_insert_position"]' );
    259258            this.$fromUrlInput    = $( '#readmo-ai-from-url' );
    260259            this.$contentTree     = $( '#readmo-ai-content-tree' );
    261260            this.$saveButton      = $( '#readmo-ai-save-auto-insert' );
    262             this.$removeButton    = $( '#readmo-ai-remove-auto-insert' );
    263             this.$modal           = $( '#readmo-ai-confirm-modal' );
    264             this.$modalCancel     = $( '#readmo-ai-modal-cancel' );
    265             this.$modalConfirm    = $( '#readmo-ai-modal-confirm' );
    266             this.$modalOverlay    = $( '.readmo-ai-modal-overlay' );
    267261        },
    268262
     
    321315            return {
    322316                enabled: this.$enabledCheckbox.is( ':checked' ),
    323                 position: $( 'input[name="auto_insert_position"]:checked' ).val(),
    324317                fromUrl: this.$fromUrlInput.val(),
    325318                excludedPostTypes: excludedPostTypes,
     
    367360            });
    368361
    369             this.$positionRadios.on( 'change', function () {
    370                 self.updateSaveButtonState();
    371             });
    372 
    373362            this.$fromUrlInput.on( 'input', function () {
    374363                self.updateSaveButtonState();
     
    402391                e.preventDefault();
    403392                self.saveSettings();
    404             });
    405 
    406             // Remove button click.
    407             this.$removeButton.on( 'click', function ( e ) {
    408                 e.preventDefault();
    409                 self.showModal();
    410             });
    411 
    412             // Modal cancel.
    413             this.$modalCancel.on( 'click', function ( e ) {
    414                 e.preventDefault();
    415                 self.hideModal();
    416             });
    417 
    418             // Modal overlay click.
    419             this.$modalOverlay.on( 'click', function () {
    420                 self.hideModal();
    421             });
    422 
    423             // Modal confirm.
    424             this.$modalConfirm.on( 'click', function ( e ) {
    425                 e.preventDefault();
    426                 self.removeSettings();
    427             });
    428 
    429             // ESC key to close modal.
    430             $( document ).on( 'keydown', function ( e ) {
    431                 if ( e.key === 'Escape' && self.$modal.is( ':visible' ) ) {
    432                     self.hideModal();
    433                 }
    434393            });
    435394        },
     
    582541                    nonce: readmoAiAdminData.nonce,
    583542                    enabled: values.enabled ? 1 : 0,
    584                     position: values.position,
    585543                    from_url: values.fromUrl,
    586544                    excluded_post_types: values.excludedPostTypes,
     
    624582                }
    625583            });
    626         },
    627 
    628         /**
    629          * Show confirmation modal.
    630          */
    631         showModal: function () {
    632             this.$modal.fadeIn( 200 );
    633         },
    634 
    635         /**
    636          * Hide confirmation modal.
    637          */
    638         hideModal: function () {
    639             this.$modal.fadeOut( 200 );
    640         },
    641 
    642         /**
    643          * Remove auto-insert settings via AJAX.
    644          */
    645         removeSettings: function () {
    646             var self = this;
    647 
    648             // Disable confirm button.
    649             this.$modalConfirm.prop( 'disabled', true ).text( readmoAiAdminData.i18n.saving );
    650 
    651             $.ajax({
    652                 type: 'POST',
    653                 url: readmoAiAdminData.ajaxUrl,
    654                 data: {
    655                     action: 'readmo_ai_delete_auto_insert_settings',
    656                     nonce: readmoAiAdminData.nonce
    657                 },
    658                 success: function ( response ) {
    659                     if ( response.success ) {
    660                         // Reset form to defaults (all checked).
    661                         self.$enabledCheckbox.prop( 'checked', false );
    662                         $( 'input[name="auto_insert_position"][value="after_content"]' ).prop( 'checked', true );
    663                         self.$fromUrlInput.val( '' );
    664 
    665                         // Check all tree items.
    666                         self.$contentTree.find( '.readmo-ai-tree-input' ).prop( 'checked', true ).prop( 'indeterminate', false );
    667                         self.$contentTree.find( '.readmo-ai-tree-node' ).removeClass( 'unchecked' );
    668 
    669                         // Update original values.
    670                         self.originalValues = self.getFormValues();
    671 
    672                         // Reset button state.
    673                         self.$saveButton
    674                             .removeClass( 'btn-secondary' )
    675                             .addClass( 'btn-ban' )
    676                             .prop( 'disabled', true );
    677 
    678                         // Hide modal.
    679                         self.hideModal();
    680 
    681                         // Re-enable confirm button.
    682                         self.$modalConfirm.prop( 'disabled', false ).text( readmoAiAdminData.i18n.confirmRemove || 'Confirm Remove' );
    683 
    684                         // Show success message.
    685                         ReadmoAiAdmin.showNotice( 'success', response.data.message );
    686                     } else {
    687                         // Show error message.
    688                         ReadmoAiAdmin.showNotice( 'error', response.data.message );
    689 
    690                         // Hide modal.
    691                         self.hideModal();
    692 
    693                         // Re-enable confirm button.
    694                         self.$modalConfirm.prop( 'disabled', false ).text( readmoAiAdminData.i18n.confirmRemove || 'Confirm Remove' );
    695                     }
    696                 },
    697                 error: function () {
    698                     // Show error message.
    699                     ReadmoAiAdmin.showNotice( 'error', 'An error occurred while removing settings.' );
    700 
    701                     // Hide modal.
    702                     self.hideModal();
    703 
    704                     // Re-enable confirm button.
    705                     self.$modalConfirm.prop( 'disabled', false ).text( readmoAiAdminData.i18n.confirmRemove || 'Confirm Remove' );
    706                 }
    707             });
    708584        }
    709585    };
  • readmo-ai/trunk/assets/svg/question.svg

    r3411004 r3447574  
    1 <svg width="28" height="28" viewBox="0 0 64 64" fill="none" xmlns="http://www.w3.org/2000/svg">
     1<svg width="24" height="24" viewBox="0 0 64 64" fill="none" xmlns="http://www.w3.org/2000/svg">
    22<g clip-path="url(#clip0_2581_15276)">
    33<path d="M43.4926 22.9982C43.5179 19.3262 42.5599 15.7144 40.7181 12.5377C38.8762 9.36101 36.2177 6.73523 33.0184 4.93294C29.819 3.13066 26.1956 2.21758 22.5243 2.28851C18.853 2.35943 15.2675 3.41177 12.1402 5.33628C9.01287 7.26076 6.45767 9.9873 4.73991 13.2327C3.02212 16.4782 2.20436 20.1243 2.37152 23.7926C2.53867 27.4608 3.68466 31.0174 5.69049 34.0932C7.6963 37.169 10.4889 39.6518 13.7783 41.2839V48.1411C13.7783 48.7473 14.0191 49.3288 14.4478 49.7571C14.8764 50.1859 15.4578 50.4268 16.064 50.4268H29.7783C30.3845 50.4268 30.9659 50.1859 31.3945 49.7571C31.8232 49.3288 32.064 48.7473 32.064 48.1411V41.2839C35.481 39.6003 38.3608 36.9972 40.3797 33.767C42.3987 30.5367 43.4766 26.8074 43.4926 22.9982Z" fill="url(#paint0_radial_2581_15276)"/>
  • readmo-ai/trunk/readme.txt

    r3447213 r3447574  
    55Tested up to: 6.9
    66Requires PHP: 7.4
    7 Stable tag: 1.2.1
     7Stable tag: 1.2.2
    88License: GPLv2 or later
    99License URI: https://www.gnu.org/licenses/gpl-2.0.html
  • readmo-ai/trunk/readmo-ai.php

    r3447213 r3447574  
    1313 * Plugin Name:       Readmo AI
    1414 * Description:       AI-powered content analysis and optimization for WordPress with analytics tracking
    15  * Version:           1.2.1
     15 * Version:           1.2.2
    1616 * Requires at least: 5.9
    1717 * Requires PHP:      7.4
     
    3333 */
    3434if ( ! defined( 'READMO_AI_VERSION' ) ) {
    35     define( 'READMO_AI_VERSION', '1.2.1' );
     35    define( 'READMO_AI_VERSION', '1.2.2' );
    3636}
    3737
Note: See TracChangeset for help on using the changeset viewer.